﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ОписаниеПеременных

Перем МножественноеЧисло Экспорт;
Перем ЕдинственноеЧисло Экспорт;
Перем МодулиПодсистем Экспорт;
Перем ПриоритетыТиповМетаданных;

#КонецОбласти

#Область ОбработчикиСобытий

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
	
	МассивНепроверяемыхРеквизитов = Новый Массив;
	
	Если ОбработчикиОбновления.Количество() = 1 Тогда
		Если СтрНайти(ОбработчикиОбновления[0].Процедура, "ПервыйЗапуск") > 0 Тогда
			МассивНепроверяемыхРеквизитов.Добавить("ОбработчикиОбновления.Версия");
		КонецЕсли;
		РежимВыполнения = ОбработчикиОбновления[0].РежимВыполнения;
		Если РежимВыполнения = "Монопольно" ИЛИ РежимВыполнения = "Оперативно" Тогда
			МассивНепроверяемыхРеквизитов.Добавить("ОбработчикиОбновления.ПроцедураЗаполненияДанныхОбновления");
			МассивНепроверяемыхРеквизитов.Добавить("ОбработчикиОбновления.Комментарий");
		КонецЕсли;
	КонецЕсли;
	
	ОбщегоНазначения.УдалитьНепроверяемыеРеквизитыИзМассива(ПроверяемыеРеквизиты, МассивНепроверяемыхРеквизитов);
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

#Область ЗаполнениеНомеровОчереди

// Заполняет номер очереди
//
// Параметры:
//  ИтерацииОбновления - Массив из см. ОбновлениеИнформационнойБазыСлужебный.ИтерацияОбновления
//
Процедура ЗаполнитьНомерОчереди(ИтерацииОбновления) Экспорт
	
	ЗагрузитьОбработчикиПодсистем(ИтерацииОбновления);
	ПостроитьОчередь(Истина);
	УстановитьНомерОчереди(ИтерацииОбновления);
	
КонецПроцедуры

// Загружает описания обработчиков конфигурации в табличные части обработки
//
Процедура ЗагрузитьОбработчики() Экспорт
	
	НачалоВсего = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Замеры = Новый Структура;
	
	ОбработчикиПодсистем = НовыйОбработчикиПодсистем();
	ОписаниеПодсистем    = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
	ПорядокБиблиотеки = 1;
	Для Каждого ИмяПодсистемы Из ОписаниеПодсистем.Порядок Цикл
		
		ОписаниеПодсистемы = ОписаниеПодсистем.ПоИменам.Получить(ИмяПодсистемы);
		Модуль             = ОбщегоНазначения.ОбщийМодуль(ОписаниеПодсистемы.ОсновнойСерверныйМодуль);
		
		Обработчики = ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления();
		Модуль.ПриДобавленииОбработчиковОбновления(Обработчики);
		
		СтрокаОбработчика = ОбработчикиПодсистем.Добавить();
		
		СтрокаОбработчика.Подсистема                            = ИмяПодсистемы;
		СтрокаОбработчика.Версия                                = СокрЛП(ОписаниеПодсистемы.Версия);
		СтрокаОбработчика.ИмяОсновногоСерверногоМодуля          = ОписаниеПодсистемы.ОсновнойСерверныйМодуль;
		СтрокаОбработчика.РежимВыполненияОтложенныхОбработчиков = ОписаниеПодсистемы.РежимВыполненияОтложенныхОбработчиков;
		СтрокаОбработчика.Обработчики                           = Обработчики;
		СтрокаОбработчика.ПорядокБиблиотеки                     = ПорядокБиблиотеки;
		
		ПорядокБиблиотеки = ПорядокБиблиотеки + 1;
	КонецЦикла;
	
	ЗагрузитьОбработчикиПодсистем(ОбработчикиПодсистем);
	
	Замеры.Вставить("ВсегоЗагрузкаОбработчиков", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоВсего)/1000));
	
КонецПроцедуры

// Загружает описания обработчиков подсистем в табличные части обработки
//
// Параметры:
//  ОбработчикиПодсистем - см. НовыйОбработчикиПодсистем
// 
Процедура ЗагрузитьОбработчикиПодсистем(ОбработчикиПодсистем)
	
	ДополнительныеСведения = Неопределено;
	Если ТипЗнч(ОбработчикиПодсистем) = Тип("Массив") Тогда
		ДополнительныеСведения = Новый Соответствие;
		ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем();
		Для Каждого Библиотека Из ОбработчикиПодсистем Цикл
			Сведения = ОписанияПодсистем.ПоИменам[Библиотека.Подсистема];
			ЕщеСведения = ЕщеСведения();
			ЕщеСведения.РежимВыполненияОтложенныхОбработчиков = Сведения.РежимВыполненияОтложенныхОбработчиков;
			ЕщеСведения.ПорядокБиблиотеки = ОписанияПодсистем.Порядок.Найти(Библиотека.Подсистема) + 1;
			ДополнительныеСведения.Вставить(Библиотека.Подсистема, ЕщеСведения);
		КонецЦикла;
	КонецЕсли;
	
	ОбработчикиОбновления.Очистить();
	ЧитаемыеОбъекты.Очистить();
	ИзменяемыеОбъекты.Очистить();
	БлокируемыеОбъекты.Очистить();
	ПриоритетыВыполнения.Очистить();
	
	МодулиПодсистем = Новый Структура;
	Для Каждого Библиотека Из ОбработчикиПодсистем Цикл
		
		Если ДополнительныеСведения = Неопределено Тогда
			ЕщеСведения = ЕщеСведения();
			ЕщеСведения.РежимВыполненияОтложенныхОбработчиков = Библиотека.РежимВыполненияОтложенныхОбработчиков;
			ЕщеСведения.ПорядокБиблиотеки = Библиотека.ПорядокБиблиотеки;
		Иначе
			ЕщеСведения = ДополнительныеСведения[Библиотека.Подсистема];
		КонецЕсли;
		
		ЗагрузитьТаблицуОбработчиков(Библиотека, ЕщеСведения);
		
		МодулиПодсистем.Вставить(Библиотека.Подсистема, Библиотека.ИмяОсновногоСерверногоМодуля);
		
	КонецЦикла;
	
	ОбновитьСведенияОКонфликтахОбработчиков();
	
КонецПроцедуры

// Определяет пересечения обработчиков по данным читаемых/изменяемых объектов
// и обновляет данные о заполненности приоритетов выполнения обработчиков.
//
// Возвращаемое значение:
//   ТаблицаЗначений - новые данные табличной части ОбработчикиОбновления
//
Функция ОбновитьСведенияОКонфликтахОбработчиков() Экспорт
	
	Запрос = ЗапросВременныхТаблиц();
	ТекстыЗапросов = Новый Массив;
	ТекстыЗапросов.Добавить(ТекстЗапросаВременныхТаблиц());
	ТекстыЗапросов.Добавить(ТекстЗапросаОбновленияДанныхОКонфликтах());
	Запрос.Текст = СтрСоединить(ТекстыЗапросов, ОбщегоНазначения.РазделительПакетаЗапросов());
	Запрос.УстановитьПараметр("Параллельно", "Параллельно");
	Запрос.УстановитьПараметр("Отложенно", "Отложенно");
	
	РезультатЗапросов = Запрос.ВыполнитьПакет();
	ИндексПоследнегоЗапроса = РезультатЗапросов.ВГраница();
	
	НовоеОписание = РезультатЗапросов[ИндексПоследнегоЗапроса].Выгрузить();
	НовоеОписание.Сортировать("Подсистема УБЫВ, Процедура");
	ОбработчикиОбновления.Загрузить(НовоеОписание);
	
	Приоритеты = РезультатЗапросов[ИндексПоследнегоЗапроса-1].Выгрузить();
	ПриоритетыВыполнения.Загрузить(Приоритеты);
	
	Конфликты = РезультатЗапросов[ИндексПоследнегоЗапроса-2].Выгрузить();
	КонфликтыОбработчиков.Загрузить(Конфликты);
	
	ЧтениеПорядка = РезультатЗапросов[ИндексПоследнегоЗапроса-3].Выгрузить();
	ЧтениеНизкогоПорядка.Загрузить(ЧтениеПорядка);
	
	
	ПриоритетыПоЗаписи = 0;
	НеПоПриоритетуЗаписи = 0;
	ОбработчикиПоЗаписи = Новый Соответствие;
	ОбработчикиНеПоЗаписи = Новый СписокЗначений;
	ВсегоРазрабатываемыхОбъектов = 0;
	ПорядкиНеРавны = 0;
	НеЛюбойПорядок = 0;
	ИнверсныйПорядок = 0;
	РазрабатываемыеПодсистемы = РазрабатываемыеПодсистемы();
	Приоритеты.Колонки.Вставить(5, "НеЛюбой", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10, 0)));
	Приоритеты.Колонки.Вставить(6, "Инверсия", Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10, 0)));
	Для Каждого Приоритет Из Приоритеты Цикл
		Если Приоритет.Порядок <> "Любой" И Приоритет.ПорядокАвто = "Любой" И НЕ Приоритет.ПовторнаяЗапись Тогда
			Приоритет.НеЛюбой = 1;
		КонецЕсли;
		Если Приоритет.Порядок = "До" И Приоритет.ПорядокАвто = "После"
			ИЛИ Приоритет.Порядок = "После" И Приоритет.ПорядокАвто = "До" Тогда
			Приоритет.Инверсия = 1;
		КонецЕсли;
		Если РазрабатываемыеПодсистемы.Найти(Приоритет.Подсистема1) <> Неопределено Тогда
			ПорядкиНеРавны = ПорядкиНеРавны + Приоритет.ПорядкиНеРавны;
			НеЛюбойПорядок = НеЛюбойПорядок + Приоритет.НеЛюбой;
			ИнверсныйПорядок = ИнверсныйПорядок + Приоритет.Инверсия;
			НеПоПриоритетуЗаписи = НеПоПриоритетуЗаписи + Приоритет.НеПоПриоритетуЗаписи;
			Если Приоритет.ПриоритетЗаписи Тогда
				ПриоритетыПоЗаписи = ПриоритетыПоЗаписи + 1;
				ОбработчикиПоЗаписи.Вставить(Приоритет.Ссылка + "_" + Приоритет.Обработчик2,Истина);
				ОбработчикиПоЗаписи.Вставить(Приоритет.Обработчик2 + "_" + Приоритет.Ссылка,Истина);
			КонецЕсли;
			ВсегоРазрабатываемыхОбъектов = ВсегоРазрабатываемыхОбъектов + 1;
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого Приоритет Из Приоритеты Цикл
		Если РазрабатываемыеПодсистемы.Найти(Приоритет.Подсистема1) <> Неопределено Тогда
			Если ОбработчикиПоЗаписи[Приоритет.Ссылка + "_" + Приоритет.Обработчик2] = Неопределено
					И ОбработчикиПоЗаписи[Приоритет.Обработчик2 + "_" + Приоритет.Ссылка] = Неопределено Тогда
				ОбработчикиНеПоЗаписи.Добавить(Приоритет.Ссылка,Приоритет.Обработчик2);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Возврат НовоеОписание;
	
КонецФункции

// По данным пересечений и указанных приоритетов выполнения обработчиков строит очередь выполнения обработчиков.
//
// Параметры:
//   БросатьИсключение - Булево - выбрасывать исключение если есть ошибки
//
// Возвращаемое значение:
//   Булево - Истина если очередь построена без ошибок
//
Функция ПостроитьОчередь(БросатьИсключение = Ложь) Экспорт
	
	НачалоВсего = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Замеры = Новый Структура;
	
	Ошибки.Очистить();
	Если ОбработчикиОбновления.Количество() = 0 Тогда
		ЗагрузитьОбработчики();
	Иначе
		ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
		ОбновитьСведенияОКонфликтахОбработчиков();
		Замеры.Вставить("ОбновитьСведенияОКонфликтахОбработчиков", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала)/1000));
	КонецЕсли;
	
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	МожноСтроитьОчередь = МожноСтроитьОчередь();
	Замеры.Вставить("МожноСтроитьОчередь", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала)/1000));
	Если НЕ МожноСтроитьОчередь Тогда
		ВывестиСообщениеОбОшибках(БросатьИсключение);
		Возврат Ложь;
	КонецЕсли;
	
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	ЕстьЦиклВыполнения = ЕстьЦиклВыполненияОбработчиков();
	Замеры.Вставить("ЕстьЦиклВыполненияОбработчиков", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала)/1000));
	Если ЕстьЦиклВыполнения Тогда
		ВывестиСообщениеОбОшибках(БросатьИсключение);
		Возврат Ложь;
	КонецЕсли;
	
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Запрос = ЗапросВременныхТаблиц();
	Запрос.УстановитьПараметр("Параллельно", "Параллельно");
	Запрос.УстановитьПараметр("Отложенно", "Отложенно");
	
	ТекстыЗапросов = Новый Массив;
	ТекстыЗапросов.Добавить(Запрос.Текст);
	ТекстыЗапросов.Добавить(ТекстВременныхТаблицПостроенияОчереди());
	
	Запрос.Текст = СтрСоединить(ТекстыЗапросов, ОбщегоНазначения.РазделительПакетаЗапросов());
	
	ОчередьОбработчиков = Новый Соответствие;
	НаличиеОбработчиковВОчереди = Новый Соответствие;
	МаксимальнаяОчередь = 1;
	
	ВыборкаПоДобавляемымОбработчикам = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	Пока ВыборкаПоДобавляемымОбработчикам.Следующий() Цикл
		
		ДобавляемыйОбработчик = ВыборкаПоДобавляемымОбработчикам.Обработчик;
		
		ОписаниеОбработчика = Новый Структура;
		ОписаниеОбработчика.Вставить("Очередь",1);
		ОписаниеОбработчика.Вставить("СвязанныеОбработчики", Новый Соответствие);
		
		ОчередьОбработчиков.Вставить(ДобавляемыйОбработчик, ОписаниеОбработчика);
		
		ДобавитьОбработчикВНаличияВОчереди(НаличиеОбработчиковВОчереди, 1, ДобавляемыйОбработчик, МаксимальнаяОчередь);
		
		Если Не ВыборкаПоДобавляемымОбработчикам.ЕстьПересечения Тогда
			Продолжить;
		КонецЕсли;
		
		ВыборкаПоСвязаннымОбработчикам = ВыборкаПоДобавляемымОбработчикам.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
		
		Пока ВыборкаПоСвязаннымОбработчикам.Следующий() Цикл
			
			СвязанныйОбработчик = ВыборкаПоСвязаннымОбработчикам.СвязанныйОбработчик;
			
			ОписаниеСвязи = Новый Структура;
			ОписаниеСвязи.Вставить("ПорядокПомещенияВОчередь", ВыборкаПоСвязаннымОбработчикам.ПорядокПомещенияВОчередь);
			ОписаниеСвязи.Вставить("ПовторнаяЗаписьОбъекта", ВыборкаПоСвязаннымОбработчикам.ЕстьПовторнаяЗапись);
			
			ОчередьОбработчиков[ДобавляемыйОбработчик].СвязанныеОбработчики.Вставить(СвязанныйОбработчик, ОписаниеСвязи); 
			
		КонецЦикла;
		
		ДанныеРекурсии = Новый Структура("Обработчик", ДобавляемыйОбработчик);
		ДанныеРекурсии.Вставить("Связанные", Новый Массив);
		ДанныеРекурсии.Вставить("Обработанные", Новый Соответствие);
		СдвинутьРекурсивноСвязанныеОбработчики(ОчередьОбработчиков, НаличиеОбработчиковВОчереди, ДобавляемыйОбработчик, МаксимальнаяОчередь, ДанныеРекурсии);
		
	КонецЦикла;
	
	// Очистим новую очередь
	Если ОбработчикиОбновления.Итог("НоваяОчередь") > 0 Тогда
		Для Каждого Описание Из ОбработчикиОбновления Цикл
			Описание.НоваяОчередь = 0;
		КонецЦикла;
	КонецЕсли;
	
	// Уберем пропуски в номерах очередей, которые могли появится из-за рекурсивных переносов
	ИзменениеНомера = 0;
	Для НомерОчереди = 1 По МаксимальнаяОчередь Цикл
		
		Если НаличиеОбработчиковВОчереди.Получить(НомерОчереди) = Неопределено
			Или НаличиеОбработчиковВОчереди[НомерОчереди].Количество() = 0 Тогда
			ИзменениеНомера = ИзменениеНомера + 1;
		Иначе 
			Для Каждого Обработчик Из НаличиеОбработчиковВОчереди[НомерОчереди] Цикл
				
				НовыйНомерОчереди = ОчередьОбработчиков[Обработчик.Ключ].Очередь - ИзменениеНомера;
				ОписаниеОбработчика = ОбработчикиОбновления.Найти(Обработчик.Ключ ,"Ссылка");
				Если ОписаниеОбработчика.НоваяОчередь <> НовыйНомерОчереди Тогда
					ОписаниеОбработчика.НоваяОчередь = НовыйНомерОчереди;
				КонецЕсли;
				
			КонецЦикла;
		КонецЕсли;
		
	КонецЦикла;
	
	МенеджерВТ = Запрос.МенеджерВременныхТаблиц;
	ОбновитьВременнуюТаблицу(МенеджерВТ, "Обработчики", ОбработчикиОбновления.Выгрузить());
	Замеры.Вставить("ПостроениеОчереди", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала)/1000));
	
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	ВсеХорошо = НЕ ЕстьОшибкиВПостроенииОчереди(Запрос);
	Замеры.Вставить("ЕстьОшибкиВПостроенииОчереди", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала)/1000));
	
	Если НЕ ВсеХорошо Тогда
		ВывестиСообщениеОбОшибках(БросатьИсключение);
	КонецЕсли;
	
	Замеры.Вставить("ВсегоВПостроенииОчереди", РазностьВремени((ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоВсего)/1000));
	
	Возврат ВсеХорошо;
	
КонецФункции

#КонецОбласти

#Область ИнициализацияИЗаполнение

Процедура ИнициализацияКонстант()
	
	МножественноеЧисло = Новый Соответствие;
	МножественноеЧисло.Вставить("Константа", "Константы");
	МножественноеЧисло.Вставить("Справочник", "Справочники");
	МножественноеЧисло.Вставить("Документ", "Документы");
	МножественноеЧисло.Вставить("ПланВидовХарактеристик", "ПланыВидовХарактеристик");
	МножественноеЧисло.Вставить("ПланОбмена", "ПланыОбмена");
	МножественноеЧисло.Вставить("ПланСчетов", "ПланыСчетов");
	МножественноеЧисло.Вставить("ПланВидовРасчета", "ПланыВидовРасчета");
	МножественноеЧисло.Вставить("РегистрСведений", "РегистрыСведений");
	МножественноеЧисло.Вставить("РегистрНакопления", "РегистрыНакопления");
	МножественноеЧисло.Вставить("РегистрБухгалтерии", "РегистрыБухгалтерии");
	МножественноеЧисло.Вставить("РегистрРасчета", "РегистрыРасчета");
	МножественноеЧисло.Вставить("БизнесПроцесс", "БизнесПроцессы");
	МножественноеЧисло.Вставить("Задача", "Задачи");
	МножественноеЧисло.Вставить("Отчет", "Отчеты");
	МножественноеЧисло.Вставить("Обработка", "Обработки");
	МножественноеЧисло.Вставить("ОбщийМодуль", "ОбщийМодуль");

	ЕдинственноеЧисло = Новый Соответствие;
	Для Каждого Класс Из МножественноеЧисло Цикл
		ЕдинственноеЧисло.Вставить(Класс.Значение, Класс.Ключ);
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

#Область ЗагрузкаОбработчиков

Процедура ЗагрузитьТаблицуОбработчиков(Библиотека, ДополнительныеСведения)
	
	Для Каждого ОписаниеОбработчика Из Библиотека.Обработчики Цикл // см. ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления
		
		Имена = СтрРазделить(ОписаниеОбработчика.Процедура, ".");
		Имена.Удалить(Имена.ВГраница());
		
		НовоеОписание = ОбработчикиОбновления.Добавить();
		НовоеОписание.Ссылка = ОписаниеОбработчика.Идентификатор;
		Если НЕ ЗначениеЗаполнено(ОписаниеОбработчика.Идентификатор) Тогда
			НовоеОписание.Ссылка = Новый УникальныйИдентификатор;
		КонецЕсли;
		ЗаполнитьЗначенияСвойств(НовоеОписание, ОписаниеОбработчика);
		НовоеОписание.Подсистема = Библиотека.Подсистема;
		НовоеОписание.ИмяОсновногоСерверногоМодуля = Библиотека.ИмяОсновногоСерверногоМодуля;
		НовоеОписание.ИмяБиблиотеки = СтрЗаменить(Библиотека.ИмяОсновногоСерверногоМодуля, "ОбновлениеИнформационнойБазы", "");
		НовоеОписание.ПорядокБиблиотеки = ДополнительныеСведения.ПорядокБиблиотеки;
		НовоеОписание.ИмяОбъекта = СтрСоединить(Имена,".");
		НовоеОписание.РежимВыполненияОтложенныхОбработчиков = ДополнительныеСведения.РежимВыполненияОтложенныхОбработчиков;
		НовоеОписание.Порядок = ОписаниеОбработчика.Порядок;
		Если НЕ ЗначениеЗаполнено(НовоеОписание.Порядок) Тогда
			НовоеОписание.Порядок = ДополнительныеСведения.Порядок;
		КонецЕсли;
		НовоеОписание.ВерсияЧислом = ВерсияЧислом(ОписаниеОбработчика.Версия);
		ЗаполнитьВерсиюРедакции(НовоеОписание);
		
		ЗагрузитьОбъектыОбработчика("ЧитаемыеОбъекты",   НовоеОписание.Ссылка, ОписаниеОбработчика.ЧитаемыеОбъекты);
		ЗагрузитьОбъектыОбработчика("ИзменяемыеОбъекты", НовоеОписание.Ссылка, ОписаниеОбработчика.ИзменяемыеОбъекты);
		ЗагрузитьОбъектыОбработчика("БлокируемыеОбъекты",НовоеОписание.Ссылка, ОписаниеОбработчика.БлокируемыеОбъекты);
		ЗагрузитьОбъектыОбработчика("НовыеОбъекты",НовоеОписание.Ссылка, ОписаниеОбработчика.НовыеОбъекты);
		ЗагрузитьПриоритетыОбработчика(НовоеОписание.Ссылка, ОписаниеОбработчика.ПриоритетыВыполнения);
	КонецЦикла;

КонецПроцедуры

Процедура ЗагрузитьОбъектыОбработчика(ИмяТабличнойЧасти, СсылкаОбработчика, ОбъектыСтрокой)
	
	Если ПустаяСтрока(ОбъектыСтрокой) Тогда
		Возврат;
	КонецЕсли;
	
	ИменаОбъектов = СтрРазделить(ОбъектыСтрокой, ",", Ложь);
	Для Каждого ИмяОбъекта Из ИменаОбъектов Цикл
		
		Если ИмяТабличнойЧасти = "БлокируемыеОбъекты" Тогда
			ВзведенФлагБлокировки = ВзвестиФлаг("БлокироватьИнтерфейс", "ИзменяемыеОбъекты", ИмяОбъекта, СсылкаОбработчика);
			Если НЕ ВзведенФлагБлокировки Тогда
				ВзведенФлагБлокировки = ВзвестиФлаг("БлокироватьИнтерфейс", "ЧитаемыеОбъекты", ИмяОбъекта, СсылкаОбработчика);
			КонецЕсли;
		КонецЕсли;
		
		Если ИмяТабличнойЧасти = "НовыеОбъекты" Тогда
			ВзвестиФлаг("НовыеОбъекты", "ИзменяемыеОбъекты", ИмяОбъекта, СсылкаОбработчика);
			Продолжить;
		КонецЕсли;
		
		Если ИмяТабличнойЧасти <> "БлокируемыеОбъекты" ИЛИ НЕ ВзведенФлагБлокировки Тогда
			ТабличнаяЧасть = ЭтотОбъект[ИмяТабличнойЧасти]; // см. Обработка.ОписаниеОбработчиковОбновления.ЧитаемыеОбъекты
			НовоеОписание = ТабличнаяЧасть.Добавить();
			НовоеОписание.Ссылка = СсылкаОбработчика;
			НовоеОписание.ОбъектМетаданных = СокрЛП(ИмяОбъекта);
			Если ИмяТабличнойЧасти <> "БлокируемыеОбъекты" Тогда
				НовоеОписание.ПорядокТипа = ПорядокТипаОбъекта(СокрЛП(ИмяОбъекта));
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Функция ВзвестиФлаг(ИмяФлага, ИмяТЧ, ИмяОбъекта, СсылкаОбработчика)
	
	Отбор = Новый Структура("Ссылка,ОбъектМетаданных", СсылкаОбработчика, ИмяОбъекта);
	НайденныеОбъекты = ЭтотОбъект[ИмяТЧ].НайтиСтроки(Отбор);
	Для Каждого НайденныйОбъект Из НайденныеОбъекты Цикл
		НайденныйОбъект[ИмяФлага] = Истина;
	КонецЦикла;
	Возврат НайденныеОбъекты.Количество() > 0;
	
КонецФункции

Процедура ЗагрузитьПриоритетыОбработчика(СсылкаОбработчика, ПриоритетыОбработчика)
	
	Если ПриоритетыОбработчика = Неопределено Тогда
		Возврат;
	КонецЕсли;
		
	Для Каждого Приоритет Из ПриоритетыОбработчика Цикл
		НовыйПриоритет = ПриоритетыВыполнения.Добавить();
		НовыйПриоритет.Ссылка = СсылкаОбработчика;
		НовыйПриоритет.Порядок = Приоритет.Порядок;
		НовыйПриоритет.Процедура2 = Приоритет.Процедура;
	КонецЦикла;
	
КонецПроцедуры

// Возвращаемое значение:
//   ТаблицаЗначений:
//   * Подсистема - Строка 
//   * Версия - Строка
//   * ИмяОсновногоСерверногоМодуля - Строка
//   * РежимВыполненияОтложенныхОбработчиков - Строка
//   * Обработчики - Строка
//   * ПорядокБиблиотеки - Число
//
Функция НовыйОбработчикиПодсистем()
	
	ОбработчикиПодсистем = Новый ТаблицаЗначений;
	
	ОбработчикиПодсистем.Колонки.Добавить("Подсистема");
	ОбработчикиПодсистем.Колонки.Добавить("Версия");
	ОбработчикиПодсистем.Колонки.Добавить("ИмяОсновногоСерверногоМодуля");
	ОбработчикиПодсистем.Колонки.Добавить("РежимВыполненияОтложенныхОбработчиков");
	ОбработчикиПодсистем.Колонки.Добавить("Обработчики");
	ОбработчикиПодсистем.Колонки.Добавить("ПорядокБиблиотеки");
	
	Возврат ОбработчикиПодсистем;
	
КонецФункции

Процедура ЗаполнитьВерсиюРедакции(Описание)
	
	Если СтрЧислоВхождений(Описание.Версия, ".") <> 3 Тогда
		Возврат;
	КонецЕсли;
	
	НомераВерсии = СтрРазделить(Описание.Версия, ".");
	НомераВерсии.Удалить(0);
	Описание.РедакцияЧислом = ВерсияЧислом(СтрСоединить(НомераВерсии, "."));
	
КонецПроцедуры

#КонецОбласти

#Область ОбнаружениеКонфликтов

Функция ТекстЗапросаОбновленияДанныхОКонфликтах()
	
	ТекстУничтожения = "УНИЧТОЖИТЬ КонфликтыОбработчиков";
	
	#Область ТекстПересечениеОбработчиков
	ТекстПересечениеОбработчиков = 
	"ВЫБРАТЬ
	|	Т.ОбъектМетаданных КАК ОбъектМетаданных,
	|	Т.ОбработчикПисатель КАК ОбработчикПисатель,
	|	МИНИМУМ(ПриоритетыОбновления1.ПорядокТипа) КАК ПорядокТипа1,
	|	Т.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	МИНИМУМ(ПриоритетыОбновления2.ПорядокТипа) КАК ПорядокТипа2,
	|	МИНИМУМ(Т.ПриоритетЗаписи) КАК ПриоритетЗаписи,
	|	МАКСИМУМ(Т.ЗаписьЧитаемых) КАК ЗаписьЧитаемых,
	|	МАКСИМУМ(Т.ПовторнаяЗапись) КАК ПовторнаяЗапись,
	|	МАКСИМУМ(Т.ЭтоЧитатель) КАК ЭтоЧитатель
	|ПОМЕСТИТЬ ПересеченияОбработчиков
	|ИЗ 
	|(
	|	// Изменяемые объекты читаются другими обработчиками
	|	ВЫБРАТЬ
	|		ИзменяемыеОбъекты.Ссылка КАК ОбработчикПисатель,
	|		ЧитаемыеОбъектыДругимиОбработчиками.Ссылка КАК ОбработчикЧитательИлиПисатель2,
	|		ИзменяемыеОбъекты.ОбъектМетаданных КАК ОбъектМетаданных,
	|		ИСТИНА КАК ПриоритетЗаписи,
	|		ИСТИНА КАК ЗаписьЧитаемых,
	|		ЛОЖЬ КАК ПовторнаяЗапись,
	|		ИСТИНА КАК ЭтоЧитатель
	|	ИЗ
	|		ИзменяемыеОбъекты КАК ИзменяемыеОбъекты
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЧитаемыеОбъекты КАК ЧитаемыеОбъектыДругимиОбработчиками
	|		ПО ИзменяемыеОбъекты.ОбъектМетаданных = ЧитаемыеОбъектыДругимиОбработчиками.ОбъектМетаданных
	|			И ИзменяемыеОбъекты.РежимВыполнения = ЧитаемыеОбъектыДругимиОбработчиками.РежимВыполнения
	|			И ИзменяемыеОбъекты.Ссылка <> ЧитаемыеОбъектыДругимиОбработчиками.Ссылка
	|	ГДЕ
	|		ИзменяемыеОбъекты.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|		И ИзменяемыеОбъекты.РежимВыполнения = &Отложенно
	|		И НЕ ИзменяемыеОбъекты.НовыеОбъекты
	|		И ЧитаемыеОбъектыДругимиОбработчиками.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|		И ЧитаемыеОбъектыДругимиОбработчиками.РежимВыполнения = &Отложенно
	|		
	|	ОБЪЕДИНИТЬ ВСЕ
	|
	|	// Изменяемые объекты изменяются другими обработчиками
	|	ВЫБРАТЬ
	|		ИзменяемыеОбъекты.Ссылка КАК ОбработчикПисатель,
	|		ИзменяемыеОбъектыДругимиОбработчиками.Ссылка КАК ОбработчикЧитательИлиПисатель2,
	|		ИзменяемыеОбъекты.ОбъектМетаданных КАК ОбъектМетаданных,
	|		ЛОЖЬ КАК ПриоритетЗаписи,
	|		ЛОЖЬ КАК ЗаписьЧитаемых,
	|		ИСТИНА КАК ПовторнаяЗапись,
	|		ЛОЖЬ КАК ЭтоЧитатель
	|	ИЗ
	|		ИзменяемыеОбъекты КАК ИзменяемыеОбъекты
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ИзменяемыеОбъекты КАК ИзменяемыеОбъектыДругимиОбработчиками
	|		ПО ИзменяемыеОбъекты.ОбъектМетаданных = ИзменяемыеОбъектыДругимиОбработчиками.ОбъектМетаданных
	|			И ИзменяемыеОбъекты.РежимВыполнения = ИзменяемыеОбъектыДругимиОбработчиками.РежимВыполнения
	|			И ИзменяемыеОбъекты.Ссылка <> ИзменяемыеОбъектыДругимиОбработчиками.Ссылка
	|	ГДЕ
	|		ИзменяемыеОбъекты.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|		И ИзменяемыеОбъекты.РежимВыполнения = &Отложенно
	|		И НЕ ИзменяемыеОбъекты.НовыеОбъекты
	|		И ИзменяемыеОбъектыДругимиОбработчиками.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|		И ИзменяемыеОбъектыДругимиОбработчиками.РежимВыполнения = &Отложенно
	|
	|) КАК Т
	|ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыОбновленияТипов КАК ПриоритетыОбновления1
	|	ПО Т.ОбработчикПисатель = ПриоритетыОбновления1.Ссылка
	|ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыОбновленияТипов КАК ПриоритетыОбновления2
	|	ПО Т.ОбработчикЧитательИлиПисатель2 = ПриоритетыОбновления2.Ссылка
	|
	|СГРУППИРОВАТЬ ПО
	|	Т.ОбъектМетаданных,
	|	Т.ОбработчикПисатель,
	|	Т.ОбработчикЧитательИлиПисатель2
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ОбработчикПисатель,
	|	ОбработчикЧитательИлиПисатель2";
	#КонецОбласти
	
	#Область ТекстВтКонфликты
	ТекстВтКонфликты = 
	"ВЫБРАТЬ
	|	Т.ОбработчикПисатель КАК ОбработчикПисатель,
	|	Т.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	МИНИМУМ(Т.ПорядокТипа1) КАК ПорядокТипа1,
	|	МИНИМУМ(Т.ПорядокТипа2) КАК ПорядокТипа2,
	|	МИНИМУМ(Т.ПриоритетЗаписи) КАК ПриоритетЗаписи,
	|	МАКСИМУМ(Т.ЗаписьЧитаемых) КАК ЗаписьЧитаемых,
	|	МАКСИМУМ(Т.ПовторнаяЗапись) КАК ПовторнаяЗапись,
	|	МАКСИМУМ(Т.ЭтоЧитатель) КАК ЭтоЧитатель
	|ПОМЕСТИТЬ втКонфликты
	|ИЗ
	|	(ВЫБРАТЬ
	|		Конфликты.ОбработчикПисатель КАК ОбработчикПисатель,
	|		Конфликты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|		Конфликты.ПорядокТипа1 КАК ПорядокТипа1,
	|		Конфликты.ПорядокТипа2 КАК ПорядокТипа2,
	|		Конфликты.ПриоритетЗаписи КАК ПриоритетЗаписи,
	|		Конфликты.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|		Конфликты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|		Конфликты.ЭтоЧитатель КАК ЭтоЧитатель
	|	ИЗ 
	|		ПересеченияОбработчиков КАК Конфликты
	|
	|	ОБЪЕДИНИТЬ ВСЕ
	|
	|	ВЫБРАТЬ
	|		Конфликты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикПисатель,
	|		Конфликты.ОбработчикПисатель КАК ОбработчикЧитательИлиПисатель2,
	|		Конфликты.ПорядокТипа2 КАК ПорядокТипа2,
	|		Конфликты.ПорядокТипа1 КАК ПорядокТипа1,
	|		НЕ Конфликты.ПриоритетЗаписи КАК ПриоритетЗаписи,
	|		Конфликты.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|		Конфликты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|		ЛОЖЬ КАК ЭтоЧитатель
	|	ИЗ 
	|		ПересеченияОбработчиков КАК Конфликты
	|	) КАК Т
	|
	|СГРУППИРОВАТЬ ПО
	|	Т.ОбработчикПисатель,
	|	Т.ОбработчикЧитательИлиПисатель2
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ОбработчикПисатель,
	|	ОбработчикЧитательИлиПисатель2";
	#КонецОбласти
	
	#Область втПриоритетыПоЗаписи
	втПриоритетыПоЗаписи = 
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Конфликты.ОбработчикПисатель КАК ОбработчикПисатель,
	|	Конфликты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	Конфликты.ПриоритетЗаписи КАК ПриоритетЗаписи
	|ПОМЕСТИТЬ втПриоритетыПоЗаписи
	|ИЗ 
	|	втКонфликты КАК Конфликты
	|ГДЕ
	|	Конфликты.ПриоритетЗаписи
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ОбработчикПисатель,
	|	ОбработчикЧитательИлиПисатель2";
	#КонецОбласти
	
	#Область ТекстВтПриоритеты
	ТекстВтПриоритеты = 
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Конфликты.ОбработчикПисатель КАК ОбработчикПисатель,
	|	Конфликты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	Конфликты.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|	КонфликтыЗеркально.ЗаписьЧитаемых КАК ЗаписьЧитаемых2,
	|	Конфликты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	КонфликтыЗеркально.ПовторнаяЗапись КАК ПовторнаяЗапись2,
	|	Конфликты.ЭтоЧитатель КАК ЭтоЧитатель,
	|	КонфликтыЗеркально.ЭтоЧитатель КАК ЭтоЧитатель2,
	|	Конфликты.ПорядокТипа1 КАК ПорядокТипа1,
	|	Конфликты.ПорядокТипа2 КАК ПорядокТипа2,
	|	ЕСТЬNULL(Обработчики1.РедакцияЧислом, 0) КАК РедакцияЧислом1,
	|	ЕСТЬNULL(Обработчики2.РедакцияЧислом, 0) КАК РедакцияЧислом2,
	|	ЕСТЬNULL(Обработчики1.ВерсияЧислом, 0) КАК ВерсияЧислом1,
	|	ЕСТЬNULL(Обработчики2.ВерсияЧислом, 0) КАК ВерсияЧислом2,
	|	ЕСТЬNULL(Обработчики1.ПорядокБиблиотеки, 0) КАК ПорядокБиблиотеки1,
	|	ЕСТЬNULL(Обработчики2.ПорядокБиблиотеки, 0) КАК ПорядокБиблиотеки2,
	|
	|	ВЫБОР КОГДА ЕСТЬNULL(Приоритеты.Порядок, &ПустаяСтрока) = ЕСТЬNULL(ПриоритетыНаоборот.Порядок, &ПустаяСтрока)
	|				И ЕСТЬNULL(Приоритеты.Порядок, &ПустаяСтрока) <> &Любой
	|		ТОГДА &ПустаяСтрока
	|		ИНАЧЕ
	|			ЕСТЬNULL(Приоритеты.Порядок,
	|					ЕСТЬNULL(ПриоритетыНаоборот.Порядок, &ПустаяСтрока))
	|	КОНЕЦ <> &ПустаяСтрока КАК ЗаданПорядокВыполнения,
	|	Конфликты.ПриоритетЗаписи КАК ПриоритетЗаписи,
	|	ВЫБОР КОГДА ЕСТЬNULL(Приоритеты.Порядок, &ПустаяСтрока) = ЕСТЬNULL(ПриоритетыНаоборот.Порядок, &ПустаяСтрока)
	|				И ЕСТЬNULL(Приоритеты.Порядок, &ПустаяСтрока) <> &Любой
	|		ТОГДА &ПустаяСтрока
	|		ИНАЧЕ
	|			ЕСТЬNULL(Приоритеты.Порядок,
	|				ЕСТЬNULL(ВЫБОР ПриоритетыНаоборот.Порядок
	|						КОГДА &До ТОГДА &После
	|						КОГДА &После ТОГДА &До
	|						КОГДА &Любой ТОГДА &Любой
	|					КОНЕЦ, 
	|					&ПустаяСтрока))
	|	КОНЕЦ КАК Порядок,
	|	ВЫБОР
	|		КОГДА Конфликты.ПриоритетЗаписи
	|			ТОГДА &До
	|		КОГДА НЕ ПриоритетыПоЗаписиЗеркально.ПриоритетЗаписи ЕСТЬ NULL
	|			ТОГДА &После
	|
	|		КОГДА Конфликты.ПорядокТипа1 = Конфликты.ПорядокТипа2 И Конфликты.ПовторнаяЗапись
	|				ИЛИ Конфликты.ПорядокТипа1 = Конфликты.ПорядокТипа2 И Конфликты.ЭтоЧитатель = КонфликтыЗеркально.ЭтоЧитатель
	|			ТОГДА &Любой
	|		КОГДА Конфликты.ПорядокТипа1 > Конфликты.ПорядокТипа2
	|			ИЛИ (Конфликты.ПорядокТипа1 = Конфликты.ПорядокТипа2 И НЕ Конфликты.ЭтоЧитатель)
	|			ТОГДА &После
	|		КОГДА Конфликты.ПорядокТипа1 < Конфликты.ПорядокТипа2
	|			ИЛИ (Конфликты.ПорядокТипа1 = Конфликты.ПорядокТипа2 И Конфликты.ЭтоЧитатель)
	|			ТОГДА &До
	|
	|		КОГДА ЕСТЬNULL(Обработчики1.ПорядокБиблиотеки, 0) = ЕСТЬNULL(Обработчики2.ПорядокБиблиотеки, 0)
	|			И ЕСТЬNULL(Обработчики1.ВерсияЧислом, 0) > ЕСТЬNULL(Обработчики2.ВерсияЧислом, 0)
	|			ТОГДА &После
	|		КОГДА ЕСТЬNULL(Обработчики1.ПорядокБиблиотеки, 0) = ЕСТЬNULL(Обработчики2.ПорядокБиблиотеки, 0)
	|			И ЕСТЬNULL(Обработчики1.ВерсияЧислом, 0) < ЕСТЬNULL(Обработчики2.ВерсияЧислом, 0)
	|			ТОГДА &До
	|		ИНАЧЕ
	|			&ПустаяСтрока
	|	КОНЕЦ КАК ПорядокАвто
	|ПОМЕСТИТЬ втПриоритеты
	|ИЗ 
	|	втКонфликты КАК Конфликты
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыВыполнения КАК Приоритеты
	|	ПО Конфликты.ОбработчикПисатель = Приоритеты.Ссылка
	|		И Конфликты.ОбработчикЧитательИлиПисатель2 = Приоритеты.Обработчик2
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыВыполнения КАК ПриоритетыНаоборот
	|	ПО Конфликты.ОбработчикПисатель = ПриоритетыНаоборот.Обработчик2
	|		И Конфликты.ОбработчикЧитательИлиПисатель2 = ПриоритетыНаоборот.Ссылка
    |
	|	ЛЕВОЕ СОЕДИНЕНИЕ втКонфликты КАК КонфликтыЗеркально
	|	ПО Конфликты.ОбработчикПисатель = КонфликтыЗеркально.ОбработчикЧитательИлиПисатель2
	|		И Конфликты.ОбработчикЧитательИлиПисатель2 = КонфликтыЗеркально.ОбработчикПисатель
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ втПриоритетыПоЗаписи КАК ПриоритетыПоЗаписиЗеркально
	|	ПО Конфликты.ОбработчикПисатель = ПриоритетыПоЗаписиЗеркально.ОбработчикЧитательИлиПисатель2
	|		И Конфликты.ОбработчикЧитательИлиПисатель2 = ПриоритетыПоЗаписиЗеркально.ОбработчикПисатель
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики1
	|	ПО Конфликты.ОбработчикПисатель = Обработчики1.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики2
	|	ПО Конфликты.ОбработчикЧитательИлиПисатель2 = Обработчики2.Ссылка
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ОбработчикПисатель,
	|	ОбработчикЧитательИлиПисатель2";
	#КонецОбласти
	
	#Область ТекстНовыеПриоритеты
	ТекстНовыеПриоритеты =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Приоритеты.ОбработчикПисатель КАК ОбработчикПисатель,
	|	Приоритеты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	ЕСТЬNULL(Обработчики1.ОчередьОтложеннойОбработки, """") КАК Очередь1,
	|	ЕСТЬNULL(Обработчики2.ОчередьОтложеннойОбработки, """") КАК Очередь2,
	|	Приоритеты.РедакцияЧислом1 КАК РедакцияЧислом1,
	|	Приоритеты.РедакцияЧислом2 КАК РедакцияЧислом2,
	|	Приоритеты.ВерсияЧислом1 КАК ВерсияЧислом1,
	|	Приоритеты.ВерсияЧислом2 КАК ВерсияЧислом2,
	|	Приоритеты.ПорядокБиблиотеки1 КАК ПорядокБиблиотеки1,
	|	Приоритеты.ПорядокБиблиотеки2 КАК ПорядокБиблиотеки2,
	|	Приоритеты.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|	Приоритеты.ЗаписьЧитаемых2 КАК ЗаписьЧитаемых2,
	|	Приоритеты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	Приоритеты.ПовторнаяЗапись2 КАК ПовторнаяЗапись2,
	|	Приоритеты.ЭтоЧитатель КАК ЭтоЧитатель,
	|	Приоритеты.ЭтоЧитатель2 КАК ЭтоЧитатель2,
	|	Приоритеты.ПорядокТипа1 КАК ПорядокТипа1,
	|	Приоритеты.ПорядокТипа2 КАК ПорядокТипа2,
	|	ВЫБОР 
	|		КОГДА Приоритеты.ЗаданПорядокВыполнения
	|			ТОГДА Приоритеты.ЗаданПорядокВыполнения
	|		ИНАЧЕ
	|			ВЫБОР
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ПорядокБиблиотеки > 0 И Обработчики2.ПорядокБиблиотеки > 0
	|					И Обработчики1.ПорядокБиблиотеки < Обработчики2.ПорядокБиблиотеки
	|					ТОГДА &До
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ПорядокБиблиотеки > 0 И Обработчики2.ПорядокБиблиотеки > 0
	|					И Обработчики1.ПорядокБиблиотеки > Обработчики2.ПорядокБиблиотеки
	|					ТОГДА &После
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ОчередьОтложеннойОбработки > 0 И Обработчики2.ОчередьОтложеннойОбработки > 0
	|					И Обработчики1.ОчередьОтложеннойОбработки < Обработчики2.ОчередьОтложеннойОбработки
	|					ТОГДА &До
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ОчередьОтложеннойОбработки > 0 И Обработчики2.ОчередьОтложеннойОбработки > 0
	|					И Обработчики1.ОчередьОтложеннойОбработки > Обработчики2.ОчередьОтложеннойОбработки
	|					ТОГДА &После
	|				ИНАЧЕ
	|					Приоритеты.ПорядокАвто
	|			КОНЕЦ <> &ПустаяСтрока
	|	КОНЕЦ КАК ЗаданПорядокВыполнения,
	|	Приоритеты.ПриоритетЗаписи КАК ПриоритетЗаписи,
	|	ВЫБОР 
	|		КОГДА Приоритеты.ЗаданПорядокВыполнения
	|			ТОГДА Приоритеты.Порядок
	|		ИНАЧЕ
	|			ВЫБОР
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ПорядокБиблиотеки > 0 И Обработчики2.ПорядокБиблиотеки > 0
	|					И Обработчики1.ПорядокБиблиотеки < Обработчики2.ПорядокБиблиотеки
	|					ТОГДА &До
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ПорядокБиблиотеки > 0 И Обработчики2.ПорядокБиблиотеки > 0
	|					И Обработчики1.ПорядокБиблиотеки > Обработчики2.ПорядокБиблиотеки
	|					ТОГДА &После
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ОчередьОтложеннойОбработки > 0 И Обработчики2.ОчередьОтложеннойОбработки > 0
	|					И Обработчики1.ОчередьОтложеннойОбработки < Обработчики2.ОчередьОтложеннойОбработки
	|					ТОГДА &До
	|				КОГДА (НЕ Обработчики1.РазрабатываемаяПодсистема ИЛИ НЕ Обработчики2.РазрабатываемаяПодсистема)
	|					И Обработчики1.ОчередьОтложеннойОбработки > 0 И Обработчики2.ОчередьОтложеннойОбработки > 0
	|					И Обработчики1.ОчередьОтложеннойОбработки > Обработчики2.ОчередьОтложеннойОбработки
	|					ТОГДА &После
	|				ИНАЧЕ
	|					Приоритеты.ПорядокАвто
	|			КОНЕЦ
	|	КОНЕЦ КАК Порядок,
	|	Приоритеты.ПорядокАвто КАК ПорядокАвто
	|ПОМЕСТИТЬ НовыеПриоритеты
	|ИЗ 
	|	втПриоритеты КАК Приоритеты
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики1
	|	ПО Приоритеты.ОбработчикПисатель = Обработчики1.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики2
	|	ПО Приоритеты.ОбработчикЧитательИлиПисатель2 = Обработчики2.Ссылка
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ОбработчикПисатель,
	|	ОбработчикЧитательИлиПисатель2";
	#КонецОбласти
	
	#Область ТекстВтЧтениеНизкогоПорядка
	ТекстВтЧтениеНизкогоПорядка = 
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Читаемые.ОбъектМетаданных КАК ОбъектМетаданных,
	|	Читаемые.Порядок КАК ПорядокЧитатель,
	|	Изменяемые.Порядок КАК ПорядокПисатель,
	|	Читаемые.Ссылка КАК Читатель,
	|	Изменяемые.Ссылка КАК Писатель,
	|	Читаемые.Процедура КАК ПроцедураЧитатель,
	|	Изменяемые.Процедура КАК ПроцедураПисатель
	|	
	|ПОМЕСТИТЬ ВтЧтениеНизкогоПорядка
	|ИЗ ЧитаемыеОбъекты КАК Читаемые
	|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ ИзменяемыеОбъекты КАК Изменяемые
	|	ПО Читаемые.ОбъектМетаданных = Изменяемые.ОбъектМетаданных
	|ГДЕ
	|	(Читаемые.Порядок = ЗНАЧЕНИЕ(Перечисление.ПорядокОбработчиковОбновления.Критичный)
	|		И Изменяемые.Порядок <> ЗНАЧЕНИЕ(Перечисление.ПорядокОбработчиковОбновления.Критичный))
	|	ИЛИ (Читаемые.Порядок = ЗНАЧЕНИЕ(Перечисление.ПорядокОбработчиковОбновления.Обычный)
	|		И Изменяемые.Порядок = ЗНАЧЕНИЕ(Перечисление.ПорядокОбработчиковОбновления.Некритичный))
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	ЧтениеНизкогоПорядка.Читатель КАК Читатель,
	|	ЧтениеНизкогоПорядка.ОбъектМетаданных КАК ОбъектМетаданных,
	|	ЧтениеНизкогоПорядка.ПорядокЧитатель КАК ПорядокЧитатель,
	|	ЧтениеНизкогоПорядка.ПорядокПисатель КАК ПорядокПисатель,
	|	ЧтениеНизкогоПорядка.ПорядокЧитатель.Порядок КАК ЧислоПорядокЧитатель,
	|	ЧтениеНизкогоПорядка.ПорядокПисатель.Порядок КАК ЧислоПорядокПисатель,
	|	Приоритеты.Порядок КАК ПриоритетыПорядок,
	|	ЧтениеНизкогоПорядка.Писатель КАК Писатель,
	|	ОбработчикиЧитатели.ИмяОбъекта КАК ОбъектЧитатель,
	|	ОбработчикиПисатели.ИмяОбъекта КАК ОбъектПисатель,
	|	ЧтениеНизкогоПорядка.ПроцедураЧитатель КАК ПроцедураЧитатель,
	|	ЧтениеНизкогоПорядка.ПроцедураПисатель КАК ПроцедураПисатель
	|ПОМЕСТИТЬ втВтЧтениеНизкогоПорядкаСФильтромПоПриоритету
	|ИЗ 
	|	ВтЧтениеНизкогоПорядка КАК ЧтениеНизкогоПорядка
	|	ЛЕВОЕ СОЕДИНЕНИЕ НовыеПриоритеты КАК Приоритеты
	|	ПО ЧтениеНизкогоПорядка.Читатель = Приоритеты.ОбработчикПисатель
	|	И ЧтениеНизкогоПорядка.Писатель = Приоритеты.ОбработчикЧитательИлиПисатель2
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиЧитатели
	|	ПО ЧтениеНизкогоПорядка.Читатель = ОбработчикиЧитатели.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиПисатели
	|	ПО ЧтениеНизкогоПорядка.Писатель = ОбработчикиПисатели.Ссылка
	|ГДЕ
	|	НЕ (ОбработчикиЧитатели.ИмяОбъекта = ОбработчикиПисатели.ИмяОбъекта
	|		И ЧтениеНизкогоПорядка.ПорядокЧитатель.Порядок < ЧтениеНизкогоПорядка.ПорядокПисатель.Порядок
	|		И Приоритеты.Порядок = ""До"")
	|";
	#КонецОбласти
	
	#Область ТекстПроблемы
	ТекстПроблемы = 
	"ВЫБРАТЬ
	|	Проблемы.Обработчик КАК Обработчик,
	|	МАКСИМУМ(Проблемы.ЗаписьЧитаемых) КАК ЗаписьЧитаемых,
	|	МАКСИМУМ(Проблемы.ПовторнаяЗапись) КАК ПовторнаяЗапись,
	|	МИНИМУМ(Проблемы.ЗаданПорядокВыполнения) КАК ЗаданПорядокВыполнения,
	|	МАКСИМУМ(Проблемы.ЧтениеНизкогоПорядка) КАК ЧтениеНизкогоПорядка
	|	
	|ПОМЕСТИТЬ Проблемы
	|ИЗ
	|	(ВЫБРАТЬ
	|		Проблемы.ОбработчикПисатель КАК Обработчик,
	|		Проблемы.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|		Проблемы.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|		Проблемы.ЗаданПорядокВыполнения КАК ЗаданПорядокВыполнения,
	|		ЛОЖЬ КАК ЧтениеНизкогоПорядка
	|	ИЗ
	|		НовыеПриоритеты КАК Проблемы
	|	
	|	ОБЪЕДИНИТЬ ВСЕ
	|
	|	ВЫБРАТЬ РАЗЛИЧНЫЕ
	|		ЧтениеНизкогоПорядка.Читатель КАК Обработчик,
	|		ЛОЖЬ КАК ЗаписьЧитаемых,
	|		ЛОЖЬ КАК ПовторнаяЗапись,
	|		ИСТИНА КАК ЗаданПорядокВыполнения,
	|		ИСТИНА КАК ЧтениеНизкогоПорядка
	|	ИЗ 
	|		втВтЧтениеНизкогоПорядкаСФильтромПоПриоритету КАК ЧтениеНизкогоПорядка) КАК Проблемы
	|
	|СГРУППИРОВАТЬ ПО
	|	Проблемы.Обработчик
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Обработчик";
	#КонецОбласти
	
	#Область ТекстЧтениеНизкогоПорядка
	ТекстЧтениеНизкогоПорядка = 
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	ЧтениеНизкогоПорядка.Читатель КАК Ссылка,
	|	ЧтениеНизкогоПорядка.ОбъектМетаданных КАК ОбъектМетаданных,
	|	ЧтениеНизкогоПорядка.ПорядокЧитатель КАК ПорядокЧитатель,
	|	ЧтениеНизкогоПорядка.ПорядокПисатель КАК ПорядокПисатель,
	|	ЧтениеНизкогоПорядка.ПорядокЧитатель.Порядок КАК ЧислоПорядокЧитатель,
	|	ЧтениеНизкогоПорядка.ПорядокПисатель.Порядок КАК ЧислоПорядокПисатель,
	|	ЧтениеНизкогоПорядка.ПриоритетыПорядок КАК ПриоритетыПорядок,
	|	ЧтениеНизкогоПорядка.Писатель КАК Писатель,
	|	ЧтениеНизкогоПорядка.ОбъектЧитатель КАК ОбъектЧитатель,
	|	ЧтениеНизкогоПорядка.ОбъектПисатель КАК ОбъектПисатель,
	|	ЧтениеНизкогоПорядка.ПроцедураЧитатель КАК ПроцедураЧитатель,
	|	ЧтениеНизкогоПорядка.ПроцедураПисатель КАК ПроцедураПисатель
	|	
	|ИЗ 
	|	втВтЧтениеНизкогоПорядкаСФильтромПоПриоритету КАК ЧтениеНизкогоПорядка
	|";
	#КонецОбласти
	
	#Область ТекстКонфликты
	ТекстКонфликты = 
	"ВЫБРАТЬ
	|	Конфликты.ОбъектМетаданных КАК ОбъектМетаданных,
	|	Конфликты.ОбработчикПисатель КАК ОбработчикПисатель,
	|	Конфликты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	Конфликты.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|	Конфликты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	Конфликты.ЭтоЧитатель КАК ЭтоЧитатель,
	|	Конфликты.ПорядокТипа1 КАК ПорядокТипа1,
	|	Конфликты.ПорядокТипа2 КАК ПорядокТипа2,
	|	ЕСТЬNULL(ОбработчикиПисатели.Процедура, """") КАК ПроцедураПисатель,
	|	ЕСТЬNULL(ОбработчикиЧитателиИлиПисатели2.Процедура, """") КАК ПроцедураЧитательИлиПисатель2
	|ИЗ 
	|	ПересеченияОбработчиков КАК Конфликты
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиПисатели
	|	ПО Конфликты.ОбработчикПисатель = ОбработчикиПисатели.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиЧитателиИлиПисатели2
	|	ПО Конфликты.ОбработчикЧитательИлиПисатель2 = ОбработчикиЧитателиИлиПисатели2.Ссылка
	|
	|УПОРЯДОЧИТЬ ПО
	|	ОбъектМетаданных,
	|	ПроцедураПисатель,
	|	ПроцедураЧитательИлиПисатель2";
	#КонецОбласти
	
	#Область ТекстПриоритеты
	ТекстПриоритеты = 
	"ВЫБРАТЬ
	|	Приоритеты.ОбработчикПисатель КАК Ссылка,
	|	Приоритеты.ОбработчикЧитательИлиПисатель2 КАК Обработчик2,
	|	Приоритеты.Порядок КАК Порядок,
	|	Приоритеты.ПорядокАвто КАК ПорядокАвто,
	|	Приоритеты.ПриоритетЗаписи КАК ПриоритетЗаписи,
	|	ВЫБОР КОГДА Приоритеты.ПриоритетЗаписи И Приоритеты.ПорядокАвто <> &До
	|		ТОГДА 1
	|		ИНАЧЕ 0
	|	КОНЕЦ КАК НеПоПриоритетуЗаписи,
	|	ВЫБОР КОГДА Приоритеты.Порядок <> Приоритеты.ПорядокАвто
	|		ТОГДА 1
	|		ИНАЧЕ 0
	|	КОНЕЦ КАК ПорядкиНеРавны,
	|	Приоритеты.ЗаданПорядокВыполнения КАК ЗаданПорядокВыполнения,
	|	Приоритеты.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|	Приоритеты.ЗаписьЧитаемых2 КАК ЗаписьЧитаемых2,
	|	Приоритеты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	Приоритеты.ПовторнаяЗапись2 КАК ПовторнаяЗапись2,
	|	Приоритеты.ЭтоЧитатель КАК ЭтоЧитатель,
	|	Приоритеты.ЭтоЧитатель2 КАК ЭтоЧитатель2,
	|	Приоритеты.ПорядокТипа1 КАК ПорядокТипа1,
	|	Приоритеты.ПорядокТипа2 КАК ПорядокТипа2,
	|	Приоритеты.РедакцияЧислом1 КАК РедакцияЧислом1,
	|	Приоритеты.РедакцияЧислом2 КАК РедакцияЧислом2,
	|	Приоритеты.ВерсияЧислом1 КАК ВерсияЧислом1,
	|	Приоритеты.ВерсияЧислом2 КАК ВерсияЧислом2,
	|	Приоритеты.ПорядокБиблиотеки1 КАК ПорядокБиблиотеки1,
	|	Приоритеты.ПорядокБиблиотеки2 КАК ПорядокБиблиотеки2,
	|	ЕСТЬNULL(ОбработчикиПисатели.Процедура, """") КАК Процедура1,
	|	ЕСТЬNULL(ОбработчикиПисатели.Подсистема, """") КАК Подсистема1,
	|	ЕСТЬNULL(ОбработчикиПисатели.Комментарий, """") КАК Комментарий1,
	|	ЕСТЬNULL(ОбработчикиЧитателиПисатели2.Процедура, """") КАК Процедура2,
	|	ЕСТЬNULL(ОбработчикиЧитателиПисатели2.Подсистема, """") КАК Подсистема2,
	|	ЕСТЬNULL(ОбработчикиЧитателиПисатели2.Комментарий, """") КАК Комментарий2
	|ИЗ
	|	НовыеПриоритеты КАК Приоритеты
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиПисатели
	|	ПО Приоритеты.ОбработчикПисатель = ОбработчикиПисатели.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиЧитателиПисатели2
	|	ПО Приоритеты.ОбработчикЧитательИлиПисатель2 = ОбработчикиЧитателиПисатели2.Ссылка
	|
	|УПОРЯДОЧИТЬ ПО
	|	Процедура1,
	|	Процедура2";
	#КонецОбласти

	#Область ТекстОписание
	ТекстОписание = 
	"ВЫБРАТЬ
	|	Обработчики.Ссылка КАК Ссылка,
	|	Обработчики.Подсистема КАК Подсистема,
	|	Обработчики.ИмяОсновногоСерверногоМодуля КАК ИмяОсновногоСерверногоМодуля,
	|	Обработчики.НачальноеЗаполнение КАК НачальноеЗаполнение,
	|	Обработчики.Версия КАК Версия,
	|	Обработчики.ВерсияЧислом КАК ВерсияЧислом,
	|	Обработчики.РедакцияЧислом КАК РедакцияЧислом,
	|	Обработчики.Процедура КАК Процедура,
	|	Обработчики.РежимВыполнения КАК РежимВыполнения,
	|	Обработчики.РежимВыполненияОтложенныхОбработчиков КАК РежимВыполненияОтложенныхОбработчиков,
	|	Обработчики.ВыполнятьВГруппеОбязательных КАК ВыполнятьВГруппеОбязательных,
	|	Обработчики.Приоритет КАК Приоритет,
	|	Обработчики.ОбщиеДанные КАК ОбщиеДанные,
	|	Обработчики.УправлениеОбработчиками КАК УправлениеОбработчиками,
	|	Обработчики.Комментарий КАК Комментарий,
	|	Обработчики.Идентификатор КАК Идентификатор,
	|	Обработчики.ПроцедураПроверки КАК ПроцедураПроверки,
	|	Обработчики.ПроцедураЗаполненияДанныхОбновления КАК ПроцедураЗаполненияДанныхОбновления,
	|	Обработчики.ОчередьОтложеннойОбработки КАК ОчередьОтложеннойОбработки,
	|	Обработчики.ЗапускатьТолькоВГлавномУзле КАК ЗапускатьТолькоВГлавномУзле,
	|	Обработчики.ЗапускатьИВПодчиненномУзлеРИБСФильтрами КАК ЗапускатьИВПодчиненномУзлеРИБСФильтрами,
	|	Обработчики.Многопоточный КАК Многопоточный,
	|	Обработчики.Изменен КАК Изменен,
	|	Обработчики.ТехническийПроект КАК ТехническийПроект,
	|	Обработчики.ИмяБиблиотеки КАК ИмяБиблиотеки,
	|	Обработчики.ПорядокБиблиотеки КАК ПорядокБиблиотеки,
	|	Обработчики.Порядок КАК Порядок,
	|	Обработчики.ИмяОбъекта КАК ИмяОбъекта,
	|	Обработчики.РазрабатываемаяПодсистема КАК РазрабатываемаяПодсистема,
	|	ЕСТЬNULL(Проблемы.ЗаписьЧитаемых, ЛОЖЬ) КАК ЗаписьЧитаемых,
	|	ЕСТЬNULL(Проблемы.ПовторнаяЗапись, ЛОЖЬ) КАК ПовторнаяЗапись,
	|	ЕСТЬNULL(Проблемы.ЗаданПорядокВыполнения, ЛОЖЬ) КАК ЗаданПорядокВыполнения,
	|	ЕСТЬNULL(Проблемы.ЧтениеНизкогоПорядка, ЛОЖЬ) КАК ЧтениеНизкогоПорядка,
	|	&НетПроблем КАК СтатусПроблемы,
	|	ВЫБОР
	|		КОГДА Обработчики.ПроцедураПроверки <> """"
	|				И Обработчики.ПроцедураПроверки <> &СтандартнаяПроцедураПроверки
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК ИзмененаПроцедураПроверки
	|ИЗ
	|	Обработчики КАК Обработчики
	|	ЛЕВОЕ СОЕДИНЕНИЕ Проблемы КАК Проблемы
	|		ПО Обработчики.Ссылка = Проблемы.Обработчик";
	#КонецОбласти
	
	МассивТекстов = Новый Массив;
	МассивТекстов.Добавить(ТекстУничтожения);
	МассивТекстов.Добавить(ТекстПересечениеОбработчиков);
	МассивТекстов.Добавить(ТекстВтКонфликты);
	МассивТекстов.Добавить(втПриоритетыПоЗаписи);
	МассивТекстов.Добавить(ТекстВтПриоритеты);
	МассивТекстов.Добавить(ТекстНовыеПриоритеты);
	МассивТекстов.Добавить(ТекстВтЧтениеНизкогоПорядка);
	МассивТекстов.Добавить(ТекстПроблемы);
	МассивТекстов.Добавить(ТекстЧтениеНизкогоПорядка);
	МассивТекстов.Добавить(ТекстКонфликты);
	МассивТекстов.Добавить(ТекстПриоритеты);
	МассивТекстов.Добавить(ТекстОписание);
	
	Текст = СтрСоединить(МассивТекстов, ОбщегоНазначения.РазделительПакетаЗапросов());
	
	Возврат Текст;
	
КонецФункции

Функция ЗапросВременныхТаблиц()
	
	Запрос = Новый Запрос;
	Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
	Запрос.Текст = ТекстЗапросаВременныхТаблиц();
	Запрос.УстановитьПараметр("НетПроблем", НСтр("ru = 'Нет проблем'"));
	Запрос.УстановитьПараметр("СтандартнаяПроцедураПроверки", "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы");
	Запрос.УстановитьПараметр("До", "До");
	Запрос.УстановитьПараметр("После", "После");
	Запрос.УстановитьПараметр("Любой", "Любой");
	Запрос.УстановитьПараметр("ПустаяСтрока", "");
	Запрос.УстановитьПараметр("РазрабатываемыеПодсистемы", РазрабатываемыеПодсистемы());
	
	Запрос.УстановитьПараметр("Обработчики", ОбработчикиОбновления.Выгрузить());
	Запрос.УстановитьПараметр("ЧитаемыеОбъекты", ЧитаемыеОбъекты.Выгрузить());
	Запрос.УстановитьПараметр("ИзменяемыеОбъекты", ИзменяемыеОбъекты.Выгрузить());
	Запрос.УстановитьПараметр("БлокируемыеОбъекты", БлокируемыеОбъекты.Выгрузить());
	Запрос.УстановитьПараметр("ПриоритетыВыполнения", ПриоритетыВыполнения.Выгрузить());
	Запрос.УстановитьПараметр("КонфликтыОбработчиков", КонфликтыОбработчиков.Выгрузить());
	
	Возврат Запрос;
	
КонецФункции

Функция ТекстЗапросаВременныхТаблиц()

	ТекстыЗапросов = Новый Массив;

	#Область ОписаниеОбработчиков
	ТекстыЗапросов.Добавить(ТекстВременнойТаблицыОбработчиков());
	#КонецОбласти

	#Область ЧитаемыеОбъекты
	ТекстЗапросаЧитаемыеОбъекты = 
	"ВЫБРАТЬ
	|	ЧитаемыеОбъекты.Ссылка КАК Ссылка,
	|	ЧитаемыеОбъекты.ОбъектМетаданных КАК ОбъектМетаданных,
	|	ЧитаемыеОбъекты.ПорядокТипа КАК ПорядокТипа,
	|	ЧитаемыеОбъекты.БлокироватьИнтерфейс КАК БлокироватьИнтерфейс,
	|	&НовыеОбъекты КАК НовыеОбъекты
	|ПОМЕСТИТЬ втЧитаемыеОбъекты
	|ИЗ
	|	&ЧитаемыеОбъекты КАК ЧитаемыеОбъекты
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Ссылка
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ЧитаемыеОбъекты.Ссылка КАК Ссылка,
	|	ЧитаемыеОбъекты.ОбъектМетаданных КАК ОбъектМетаданных,
	|	ЧитаемыеОбъекты.ПорядокТипа КАК ПорядокТипа,
	|	Обработчики.РежимВыполнения КАК РежимВыполнения,
	|	Обработчики.НачальноеЗаполнение КАК НачальноеЗаполнение,
	|	Обработчики.Процедура КАК Процедура,
	|	Обработчики.Порядок КАК Порядок,
	|	Обработчики.РежимВыполненияОтложенныхОбработчиков КАК РежимВыполненияОтложенныхОбработчиков,
	|	ЧитаемыеОбъекты.БлокироватьИнтерфейс КАК БлокироватьИнтерфейс,
	|	ЧитаемыеОбъекты.НовыеОбъекты КАК НовыеОбъекты
	|ПОМЕСТИТЬ ЧитаемыеОбъекты
	|ИЗ
	|	втЧитаемыеОбъекты КАК ЧитаемыеОбъекты
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики
	|	ПО ЧитаемыеОбъекты.Ссылка = Обработчики.Ссылка
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Ссылка,
	|	ОбъектМетаданных
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|УНИЧТОЖИТЬ втЧитаемыеОбъекты";
	ТекстыЗапросов.Добавить(СтрЗаменить(ТекстЗапросаЧитаемыеОбъекты, "&НовыеОбъекты", "ЛОЖЬ"));
	#КонецОбласти

	#Область ИзменяемыеОбъекты
	ТекстЗапросаИзменяемыеОбъекты = СтрЗаменить(ТекстЗапросаЧитаемыеОбъекты, "&НовыеОбъекты", "ЧитаемыеОбъекты.НовыеОбъекты");
	ТекстЗапросаИзменяемыеОбъекты = СтрЗаменить(ТекстЗапросаИзменяемыеОбъекты, "ЧитаемыеОбъекты", "ИзменяемыеОбъекты");
	ТекстыЗапросов.Добавить(СтрЗаменить(ТекстЗапросаИзменяемыеОбъекты, "ЧитаемыеОбъекты", "ИзменяемыеОбъекты"));
	#КонецОбласти

	#Область ПриоритетыОбновленияТипов
	ТекстЗапросаПриоритетыОбновленияТипов = 
	"ВЫБРАТЬ
	|	ИзменяемыеОбъекты.Ссылка КАК Ссылка,
	|	МИНИМУМ(ИзменяемыеОбъекты.ПорядокТипа) КАК ПорядокТипа
	|ПОМЕСТИТЬ ПриоритетыОбновленияТипов
	|ИЗ
	|	ИзменяемыеОбъекты КАК ИзменяемыеОбъекты
	|СГРУППИРОВАТЬ ПО
	|	ИзменяемыеОбъекты.Ссылка
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Ссылка";
	ТекстыЗапросов.Добавить(ТекстЗапросаПриоритетыОбновленияТипов);
	#КонецОбласти

	#Область БлокируемыеОбъекты
	ТекстыЗапросов.Добавить(
	"ВЫБРАТЬ
	|	БлокируемыеОбъекты.Ссылка КАК Ссылка,
	|	БлокируемыеОбъекты.ОбъектМетаданных КАК ОбъектМетаданных
	|ПОМЕСТИТЬ БлокируемыеОбъекты
	|ИЗ
	|	&БлокируемыеОбъекты КАК БлокируемыеОбъекты");
	#КонецОбласти

	#Область ПриоритетыВыполнения
	ТекстыЗапросов.Добавить(
	"ВЫБРАТЬ
	|	ПриоритетыВыполнения.Ссылка КАК Ссылка,
	|	ПриоритетыВыполнения.Порядок КАК Порядок,
	|	ПриоритетыВыполнения.Процедура2 КАК Процедура2,
	|	ПриоритетыВыполнения.ЗаданПорядокВыполнения КАК ЗаданПорядокВыполнения,
	|	ПриоритетыВыполнения.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	ПриоритетыВыполнения.ЗаписьЧитаемых КАК ЗаписьЧитаемых
	|ПОМЕСТИТЬ втПриоритеты
	|ИЗ
	|	&ПриоритетыВыполнения КАК ПриоритетыВыполнения
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Процедура2
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ПриоритетыВыполнения.Ссылка КАК Ссылка,
	|	Обработчики2.Ссылка КАК Обработчик2,
	|	ПриоритетыВыполнения.Порядок КАК Порядок,
	|	Обработчики1.Процедура КАК Процедура,
	|	ПриоритетыВыполнения.Процедура2 КАК Процедура2,
	|	ПриоритетыВыполнения.ЗаданПорядокВыполнения КАК ЗаданПорядокВыполнения,
	|	ПриоритетыВыполнения.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	ПриоритетыВыполнения.ЗаписьЧитаемых КАК ЗаписьЧитаемых
	|ПОМЕСТИТЬ ПриоритетыВыполнения
	|ИЗ
	|	втПриоритеты КАК ПриоритетыВыполнения
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики1
	|	ПО ПриоритетыВыполнения.Ссылка = Обработчики1.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики2
	|	ПО ПриоритетыВыполнения.Процедура2 = Обработчики2.Процедура
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Ссылка,
	|	Обработчик2
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|УНИЧТОЖИТЬ втПриоритеты");
	#КонецОбласти
	
	#Область КонфликтыОбработчиков
	ТекстыЗапросов.Добавить(
	"ВЫБРАТЬ
	|	КонфликтыОбработчиков.ОбработчикПисатель КАК ОбработчикПисатель,
	|	КонфликтыОбработчиков.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|	КонфликтыОбработчиков.ОбъектМетаданных КАК ОбъектМетаданных,
	|	КонфликтыОбработчиков.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|	КонфликтыОбработчиков.ПовторнаяЗапись КАК ПовторнаяЗапись
	|ПОМЕСТИТЬ КонфликтыОбработчиков
	|ИЗ
	|	&КонфликтыОбработчиков КАК КонфликтыОбработчиков
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	ОбработчикПисатель,
	|	ОбработчикЧитательИлиПисатель2,
	|	ОбъектМетаданных");
	#КонецОбласти

	Возврат СтрСоединить(ТекстыЗапросов, ОбщегоНазначения.РазделительПакетаЗапросов());

КонецФункции

Функция ТекстВременнойТаблицыОбработчиков()
	
	Возврат
	"ВЫБРАТЬ
	|	Обработчики.Ссылка КАК Ссылка,
	|	Обработчики.Подсистема КАК Подсистема,
	|	Обработчики.ИмяОсновногоСерверногоМодуля КАК ИмяОсновногоСерверногоМодуля,
	|	Обработчики.НачальноеЗаполнение КАК НачальноеЗаполнение,
	|	Обработчики.Версия КАК Версия,
	|	Обработчики.ВерсияЧислом КАК ВерсияЧислом,
	|	Обработчики.РедакцияЧислом КАК РедакцияЧислом,
	|	Обработчики.Процедура КАК Процедура,
	|	Обработчики.РежимВыполнения КАК РежимВыполнения,
	|	Обработчики.РежимВыполненияОтложенныхОбработчиков КАК РежимВыполненияОтложенныхОбработчиков,
	|	Обработчики.ВыполнятьВГруппеОбязательных КАК ВыполнятьВГруппеОбязательных,
	|	Обработчики.Приоритет КАК Приоритет,
	|	Обработчики.ОбщиеДанные КАК ОбщиеДанные,
	|	Обработчики.УправлениеОбработчиками КАК УправлениеОбработчиками,
	|	Обработчики.Комментарий КАК Комментарий,
	|	Обработчики.Идентификатор КАК Идентификатор,
	|	Обработчики.ПроцедураПроверки КАК ПроцедураПроверки,
	|	Обработчики.ПроцедураЗаполненияДанныхОбновления КАК ПроцедураЗаполненияДанныхОбновления,
	|	Обработчики.ОчередьОтложеннойОбработки КАК ОчередьОтложеннойОбработки,
	|	Обработчики.НоваяОчередь КАК НоваяОчередь,
	|	Обработчики.ЗапускатьТолькоВГлавномУзле КАК ЗапускатьТолькоВГлавномУзле,
	|	Обработчики.ЗапускатьИВПодчиненномУзлеРИБСФильтрами КАК ЗапускатьИВПодчиненномУзлеРИБСФильтрами,
	|	Обработчики.Многопоточный КАК Многопоточный,
	|	Обработчики.СтатусПроблемы КАК СтатусПроблемы,
	|	Обработчики.ЗаписьЧитаемых КАК ЗаписьЧитаемых,
	|	Обработчики.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	Обработчики.Изменен КАК Изменен,
	|	Обработчики.ТехническийПроект КАК ТехническийПроект,
	|	Обработчики.ИмяБиблиотеки КАК ИмяБиблиотеки,
	|	Обработчики.ПорядокБиблиотеки КАК ПорядокБиблиотеки,
	|	Обработчики.Порядок КАК Порядок,
	|	Обработчики.ИмяОбъекта КАК ИмяОбъекта,
	|	Обработчики.Подсистема В (&РазрабатываемыеПодсистемы) КАК РазрабатываемаяПодсистема
	|ПОМЕСТИТЬ Обработчики
	|ИЗ
	|	&Обработчики КАК Обработчики
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Ссылка,
	|	Процедура";
	
КонецФункции

#КонецОбласти

#Область ПостроениеОчереди

Функция ТекстВременныхТаблицПостроенияОчереди()

	Возврат
	"ВЫБРАТЬ
	|	Конфликты.ОбработчикПисатель КАК ОбработчикПисатель,
	|	Конфликты.ОбработчикЧитательИлиПисатель2 КАК ОбработчикЧитательИлиПисатель2,
	|
	|	ОбработчикиПисатели.РежимВыполнения КАК РежимВыполнения1,
	|	ОбработчикиЧитателиПисатели2.РежимВыполнения КАК РежимВыполнения2,
	|
	|	Конфликты.ПовторнаяЗапись КАК ПовторнаяЗапись,
	|	ОбработчикиПисатели.Процедура КАК Процедура1,
	|	ОбработчикиЧитателиПисатели2.Процедура КАК Процедура2
	|
	|ПОМЕСТИТЬ ПроблемыОбработчиков
	|ИЗ
	|	КонфликтыОбработчиков КАК Конфликты
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиПисатели
	|	ПО Конфликты.ОбработчикПисатель = ОбработчикиПисатели.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК ОбработчикиЧитателиПисатели2
	|	ПО Конфликты.ОбработчикЧитательИлиПисатель2 = ОбработчикиЧитателиПисатели2.Ссылка
	|
	|ГДЕ
	|	ОбработчикиПисатели.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|	И ОбработчикиПисатели.РежимВыполнения = &Отложенно
	|
	|	И ОбработчикиЧитателиПисатели2.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|	И ОбработчикиЧитателиПисатели2.РежимВыполнения = &Отложенно
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	Приоритеты.Ссылка КАК Обработчик1,
	|	Приоритеты.Обработчик2 КАК Обработчик2,
	|	Приоритеты.Порядок КАК Порядок,
	|
	|	Обработчики1.ВерсияЧислом КАК ВерсияЧислом1,
	|	Обработчики1.Процедура КАК Процедура1,
	|
	|	Обработчики2.ВерсияЧислом КАК ВерсияЧислом2,
	|	Обработчики2.Процедура КАК Процедура2,
	|
	|	Обработчики1.РежимВыполнения КАК РежимВыполнения1,
	|	Обработчики2.РежимВыполнения КАК РежимВыполнения2
	|
	|ПОМЕСТИТЬ ПриоритетыОбработчиков
	|ИЗ
	|	ПриоритетыВыполнения КАК Приоритеты
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики1
	|	ПО Приоритеты.Ссылка = Обработчики1.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики2
	|	ПО Приоритеты.Обработчик2 = Обработчики2.Ссылка
	|
	|ГДЕ
	|	Обработчики1.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|	И Обработчики1.РежимВыполнения = &Отложенно
	|
	|	И Обработчики2.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|	И Обработчики2.РежимВыполнения = &Отложенно
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	Т.Обработчик КАК Обработчик,
	|	Т.ВерсияЧислом КАК ВерсияЧислом,
	|	Т.Процедура КАК Процедура,
	|	СУММА(Т.КоличествоПересечений) КАК КоличествоПересечений,
	|	СУММА(Т.КоличествоСначалаОбработчик1) КАК КоличествоСначалаОбработчик1,
	|	СУММА(Т.КоличествоЛюбойПорядок) КАК КоличествоЛюбойПорядок
	|ПОМЕСТИТЬ ПересеченияОбработчиков
	|ИЗ
	|	(ВЫБРАТЬ
	|		ОбработчикиОбновления.Ссылка КАК Обработчик,
	|		ОбработчикиОбновления.ВерсияЧислом КАК ВерсияЧислом,
	|		ОбработчикиОбновления.Процедура КАК Процедура,
	|		0 КАК КоличествоПересечений,
	|		0 КАК КоличествоСначалаОбработчик1,
	|		0 КАК КоличествоЛюбойПорядок
	|	ИЗ
	|		Обработчики КАК ОбработчикиОбновления
	|	ГДЕ
	|		ОбработчикиОбновления.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|		И ОбработчикиОбновления.РежимВыполнения = &Отложенно
	|	
	|	ОБЪЕДИНИТЬ ВСЕ
	|	
	|	ВЫБРАТЬ
	|		Приоритеты.Обработчик1 КАК Обработчик,
	|		Приоритеты.ВерсияЧислом1 КАК ВерсияЧислом,
	|		Приоритеты.Процедура1 КАК Процедура,
	|		1 КАК КоличествоПересечений,
	|		ВЫБОР
	|			КОГДА Приоритеты.Порядок = &До
	|				ТОГДА 1
	|			ИНАЧЕ 0
	|		КОНЕЦ КАК КоличествоСначалаОбработчик1,
	|		ВЫБОР
	|			КОГДА Приоритеты.Порядок = &Любой
	|				ТОГДА 1
	|			ИНАЧЕ 0
	|		КОНЕЦ КАК КоличествоЛюбойПорядок
	|	ИЗ
	|		ПриоритетыОбработчиков КАК Приоритеты
	|	) КАК Т
	|
	|СГРУППИРОВАТЬ ПО
	|	Т.Обработчик,
	|	Т.Процедура,
	|	Т.ВерсияЧислом
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ПроблемыОбработчиков.ОбработчикПисатель КАК Обработчик1,
	|	ПроблемыОбработчиков.ОбработчикЧитательИлиПисатель2 КАК Обработчик2,
	|	МАКСИМУМ(ПроблемыОбработчиков.ПовторнаяЗапись) КАК ЕстьПовторнаяЗапись
	|ПОМЕСТИТЬ ПовторнаяЗапись
	|ИЗ
	|	ПроблемыОбработчиков КАК ПроблемыОбработчиков
	|
	|СГРУППИРОВАТЬ ПО
	|	ПроблемыОбработчиков.ОбработчикПисатель,
	|	ПроблемыОбработчиков.ОбработчикЧитательИлиПисатель2
	|
	|ИМЕЮЩИЕ
	|	МАКСИМУМ(ПроблемыОбработчиков.ПовторнаяЗапись) = ИСТИНА
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	Пересечения.Обработчик КАК Обработчик,
	|	Пересечения.ВерсияЧислом КАК ВерсияЧислом,
	|	Пересечения.Процедура КАК Процедура,
	|	Пересечения.КоличествоПересечений <> 0 КАК ЕстьПересечения,
	|	Пересечения.КоличествоСначалаОбработчик1 КАК СначалаОбработчик1,
	|	Пересечения.КоличествоЛюбойПорядок КАК ЛюбойПорядок,
	|	ЕСТЬNULL(Приоритеты.Обработчик2, """") КАК СвязанныйОбработчик,
	|	ЕСТЬNULL(Приоритеты.ВерсияЧислом2, 0) КАК СвязаннаяВерсияЧислом,
	|	ЕСТЬNULL(Приоритеты.Процедура2, """") КАК СвязаннаяПроцедура,
	|	ЕСТЬNULL(Приоритеты.Порядок, """") КАК ПорядокПомещенияВОчередь,
	|	ЕСТЬNULL(ПовторнаяЗапись.ЕстьПовторнаяЗапись, ЛОЖЬ) КАК ЕстьПовторнаяЗапись
	|ИЗ
	|	ПересеченияОбработчиков КАК Пересечения
	|		ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыОбработчиков КАК Приоритеты
	|		ПО Пересечения.Обработчик = Приоритеты.Обработчик1
	|
	|			ЛЕВОЕ СОЕДИНЕНИЕ ПовторнаяЗапись КАК ПовторнаяЗапись
	|			ПО Приоритеты.Обработчик1 = ПовторнаяЗапись.Обработчик1
	|				И Приоритеты.Обработчик2 = ПовторнаяЗапись.Обработчик2
	|
	|УПОРЯДОЧИТЬ ПО
	|	ЕстьПересечения,
	|	СначалаОбработчик1 УБЫВ,
	|	ЛюбойПорядок УБЫВ,
	|	ВерсияЧислом,
	|	Процедура,
	|	СвязаннаяВерсияЧислом,
	|	СвязаннаяПроцедура
	|ИТОГИ
	|	МАКСИМУМ(ЕстьПересечения)
	|ПО
	|	Обработчик";

КонецФункции

Процедура ДобавитьОбработчикВНаличияВОчереди(НаличиеОбработчиковВОчереди, Очередь, Обработчик, МаксимальнаяОчередь)
	Если НаличиеОбработчиковВОчереди.Получить(Очередь) = Неопределено Тогда
		НаличиеОбработчиковВОчереди.Вставить(Очередь, Новый Соответствие);
	КонецЕсли;
	НаличиеОбработчиковВОчереди[Очередь].Вставить(Обработчик);
	
	Если МаксимальнаяОчередь < Очередь Тогда
		МаксимальнаяОчередь = Очередь;
	КонецЕсли;
КонецПроцедуры

Процедура СдвинутьРекурсивноСвязанныеОбработчики(ОчередьОбработчиков, НаличиеОбработчиковВОчереди, Обработчик, МаксимальнаяОчередь, ДанныеРекурсии)
	
	СвязанныеОбработчики = ОчередьОбработчиков[Обработчик].СвязанныеОбработчики;
	
	Для каждого СвязанныйОбработчик Из СвязанныеОбработчики Цикл
		
		Если Обработчик = СвязанныйОбработчик.Ключ Тогда
			Продолжить;
		КонецЕсли;
		
		Если ОчередьОбработчиков[СвязанныйОбработчик.Ключ] = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если СвязанныйОбработчик.Значение.ПорядокПомещенияВОчередь = "Любой" Тогда
			
			Если СвязанныйОбработчик.Значение.ПовторнаяЗаписьОбъекта
				И ОчередьОбработчиков[Обработчик].Очередь = ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь Тогда
				
				УдалитьОбработчикИзНаличияВОчереди(НаличиеОбработчиковВОчереди, ОчередьОбработчиков[Обработчик].Очередь, Обработчик);
				ОчередьОбработчиков[Обработчик].Очередь = ОчередьОбработчиков[Обработчик].Очередь + 1;
				ДобавитьОбработчикВНаличияВОчереди(НаличиеОбработчиковВОчереди, ОчередьОбработчиков[Обработчик].Очередь, Обработчик, МаксимальнаяОчередь);

				// Сдвинуть уже отработанные связанные обработчики
				СдвинутьРекурсивноСвязанныеОбработчики(ОчередьОбработчиков, НаличиеОбработчиковВОчереди, Обработчик, МаксимальнаяОчередь, ДанныеРекурсии);
			КонецЕсли;
			
		ИначеЕсли СвязанныйОбработчик.Значение.ПорядокПомещенияВОчередь = "До" Тогда
			
			Если ОчередьОбработчиков[Обработчик].Очередь >= ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь Тогда
				
				УдалитьОбработчикИзНаличияВОчереди(НаличиеОбработчиковВОчереди, ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь, СвязанныйОбработчик.Ключ);
				ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь = ОчередьОбработчиков[Обработчик].Очередь + 1;
				ДобавитьОбработчикВНаличияВОчереди(НаличиеОбработчиковВОчереди, ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь, СвязанныйОбработчик.Ключ, МаксимальнаяОчередь);
				
				// Сдвинуть связанные обработчики связанного обработчика
				СдвинутьРекурсивноСвязанныеОбработчики(ОчередьОбработчиков, НаличиеОбработчиковВОчереди, СвязанныйОбработчик.Ключ, МаксимальнаяОчередь, ДанныеРекурсии);
			КонецЕсли;
			
		ИначеЕсли СвязанныйОбработчик.Значение.ПорядокПомещенияВОчередь = "После" Тогда
			
			Если ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь >= ОчередьОбработчиков[Обработчик].Очередь Тогда
				
				УдалитьОбработчикИзНаличияВОчереди(НаличиеОбработчиковВОчереди, ОчередьОбработчиков[Обработчик].Очередь, Обработчик);
				ОчередьОбработчиков[Обработчик].Очередь = ОчередьОбработчиков[СвязанныйОбработчик.Ключ].Очередь + 1;
				ДобавитьОбработчикВНаличияВОчереди(НаличиеОбработчиковВОчереди, ОчередьОбработчиков[Обработчик].Очередь, Обработчик, МаксимальнаяОчередь);
				
				// Сдвинуть уже отработанные связанные обработчики
				СдвинутьРекурсивноСвязанныеОбработчики(ОчередьОбработчиков, НаличиеОбработчиковВОчереди, Обработчик, МаксимальнаяОчередь, ДанныеРекурсии);
			КонецЕсли;
			
		Иначе
			ТекстИсключения = НСтр("ru = 'Ошибка при формировании очереди.'");
			ВызватьИсключение ТекстИсключения;
		КонецЕсли;
	
	КонецЦикла;
	
КонецПроцедуры

Процедура УдалитьОбработчикИзНаличияВОчереди(НаличиеОбработчиковВОчереди, Очередь, Обработчик)
	НаличиеОбработчиковВОчереди[Очередь].Удалить(Обработчик);
КонецПроцедуры

Функция ЕстьОшибкиВПостроенииОчереди(Запрос, СообщатьОбОшибках = Истина)
	
	ТекстЗапроса =
	"ВЫБРАТЬ
	|	ПриоритетыОбработчиков.Процедура1 КАК Обработчик1,
	|	ПриоритетыОбработчиков.Процедура2 КАК Обработчик2,
	|	""ПроблемаВПорядкеСледованияОбработчиков"" КАК Проблема
	|ИЗ
	|	ПриоритетыОбработчиков КАК ПриоритетыОбработчиков
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПовторнаяЗапись КАК ДвойнаяЗапись
	|	ПО ПриоритетыОбработчиков.Обработчик1 = ДвойнаяЗапись.Обработчик1
	|		И ПриоритетыОбработчиков.Обработчик2 = ДвойнаяЗапись.Обработчик2
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики1
	|	ПО ПриоритетыОбработчиков.Обработчик1 = Обработчики1.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики2
	|	ПО ПриоритетыОбработчиков.Обработчик2 = Обработчики2.Ссылка
	|
	|ГДЕ
	|	(ПриоритетыОбработчиков.Порядок = &До
	|			И Обработчики1.НоваяОчередь >= Обработчики2.НоваяОчередь
	|		ИЛИ ПриоритетыОбработчиков.Порядок = &Любой
	|			И НЕ ДвойнаяЗапись.Обработчик1 ЕСТЬ NULL 
	|			И Обработчики1.НоваяОчередь = Обработчики2.НоваяОчередь)
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	Обработчики.Процедура КАК Обработчик1,
	|	"""" КАК Обработчик2,
	|	""ПроблемаНеПерваяОчередь"" КАК Проблема
	|ИЗ
	|	Обработчики КАК Обработчики
	|		ЛЕВОЕ СОЕДИНЕНИЕ ПриоритетыОбработчиков КАК ПриоритетыОбработчиков
	|		ПО Обработчики.Ссылка = ПриоритетыОбработчиков.Обработчик1
	|ГДЕ
	|	НЕ Обработчики.НачальноеЗаполнение
	|	И Обработчики.РежимВыполненияОтложенныхОбработчиков = &Параллельно
	|	И Обработчики.РежимВыполнения = &Отложенно
	|	И Обработчики.НоваяОчередь <> 1
	|	И ПриоритетыОбработчиков.Обработчик1 ЕСТЬ NULL "; 
	
	Запрос.Текст = ТекстЗапроса;
	
	РезультатЗапроса = Запрос.Выполнить();
	ЕстьПроблема = НЕ РезультатЗапроса.Пустой();
	
	Выборка = РезультатЗапроса.Выбрать();
	Пока Выборка.Следующий() Цикл
		ТекстСообщения = НСтр("ru = 'Ошибка в алгоритме построения очереди: обработчик %Обработчик1% должен быть отнесен к очереди 1.'");
		Если Выборка.Проблема = "ПроблемаВПорядкеСледованияОбработчиков" Тогда
			ТекстСообщения = НСтр("ru = 'Ошибка в алгоритме построения очереди: обработчики %Обработчик1% и %Обработчик2% размещены в неправильном порядке.'");
			ТекстСообщения = СтрЗаменить(ТекстСообщения, "%Обработчик2%", Выборка.Обработчик2);
		КонецЕсли;
		ТекстСообщения = СтрЗаменить(ТекстСообщения, "%Обработчик1%", Выборка.Обработчик1);
		Если СообщатьОбОшибках Тогда
			ОбщегоНазначения.СообщитьПользователю(ТекстСообщения);
		КонецЕсли;
		ДобавитьОшибку(Выборка.Обработчик1, ТекстСообщения);
	КонецЦикла;
		
	Возврат ЕстьПроблема;
	
КонецФункции

Функция МожноСтроитьОчередь()
	
	Запрос = ЗапросВременныхТаблиц();
	
	ТекстЗапроса =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	ЕСТЬNULL(Обработчики1.Процедура, """") КАК Обработчик1,
	|	ЕСТЬNULL(Обработчики2.Процедура, """") КАК Обработчик2
	|ИЗ
	|	ПриоритетыВыполнения КАК Приоритеты
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики1
	|	ПО Приоритеты.Ссылка = Обработчики1.Ссылка
	|
	|	ЛЕВОЕ СОЕДИНЕНИЕ Обработчики КАК Обработчики2
	|	ПО Приоритеты.Обработчик2 = Обработчики2.Ссылка
	|
	|ГДЕ
	|	НЕ Обработчики1.НачальноеЗаполнение
	|	И НЕ Обработчики2.НачальноеЗаполнение
	|	И НЕ Приоритеты.ЗаданПорядокВыполнения
	|
	|УПОРЯДОЧИТЬ ПО
	|	Обработчик1,
	|	Обработчик2";
	
	ТекстыЗапросов = Новый Массив;
	ТекстыЗапросов.Добавить(Запрос.Текст);
	ТекстыЗапросов.Добавить(ТекстЗапроса);
	Запрос.Текст = СтрСоединить(ТекстыЗапросов, ОбщегоНазначения.РазделительПакетаЗапросов());
	
	ПустыеПриоритеты = Запрос.Выполнить().Выбрать();
	ВсеХорошо = ПустыеПриоритеты.Количество() = 0;
	Пока ПустыеПриоритеты.Следующий() Цикл
		ТекстСообщения = НСтр("ru = 'Не завершены работы по паре обработчиков %Обработчик% - %СвязанныйОбработчик%.'");
		ТекстСообщения = ТекстСообщения + Символы.ПС + НСтр("ru = 'Статус проблемы: %ПорядокПомещенияВОчередь%'");
		ТекстСообщения = СтрЗаменить(ТекстСообщения, "%Обработчик%", ПустыеПриоритеты.Обработчик1);
		ТекстСообщения = СтрЗаменить(ТекстСообщения, "%СвязанныйОбработчик%", ПустыеПриоритеты.Обработчик2);
		ТекстСообщения = СтрЗаменить(ТекстСообщения, "%ПорядокПомещенияВОчередь%", НСтр("ru = 'Не задан приоритет выполнения.'"));
		ДобавитьОшибку(ПустыеПриоритеты.Обработчик1, ТекстСообщения);
	КонецЦикла;
	
	ВсеХорошо = ВсеХорошо И ЧтениеНизкогоПорядка.Количество() = 0;
	ОшибочныеПриоритеты = ЧтениеНизкогоПорядка.Выгрузить();
	ОшибочныеПриоритеты.Свернуть("ПроцедураЧитатель");
	Для Каждого Обработчик Из ОшибочныеПриоритеты Цикл
		ТекстСообщения = НСтр("ru = 'Среди читаемых объектов обработчика %Обработчик% 
		|имеются объекты, которые обрабатываются обработчиками с более низким приоритетом чем текущий.
		|Это приведет к тому что текущий обработчик будет ждать их завершения. Необходимо устранить это несоответствие.'");
		ТекстСообщения = СтрЗаменить(ТекстСообщения, "%Обработчик%", Обработчик.ПроцедураЧитатель);
		ДобавитьОшибку(Обработчик.ПроцедураЧитатель, ТекстСообщения);
	КонецЦикла;
	
	Возврат ВсеХорошо;
	
КонецФункции

Процедура ДобавитьОшибку(ПроцедураОбработчик, ТекстСообщения)
	
	НоваяОшибка = Ошибки.Добавить();
	НоваяОшибка.ОбъектМетаданных = ИмяОбъектаИзПроцедурыОбработки(ПроцедураОбработчик);
	НоваяОшибка.Обработчик = ПроцедураОбработчик;
	НоваяОшибка.Сообщение = ТекстСообщения;
	
КонецПроцедуры

Процедура ОбновитьВременнуюТаблицу(МенеджерВТ, ИмяТаблицы, НоваяТаблица, ПоляИндексирования = "Ссылка")
	
	Запрос = Новый Запрос;
	Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
	
	ТекстЗапросаУничтожитьВТ = "";
	Если Запрос.МенеджерВременныхТаблиц.Таблицы.Найти(ИмяТаблицы) <> Неопределено Тогда
		ТекстЗапросаУничтожитьВТ = "УНИЧТОЖИТЬ " + ИмяТаблицы + ";
		|";
	КонецЕсли;
	
	ТекстЗапросаВТ =
	"ВЫБРАТЬ
	|&Поля
	|ПОМЕСТИТЬ ИмяПриемника
	|ИЗ
	|	&Таблица КАК Т";
	
	МассивПолей = Новый Массив;
	Для Каждого Колонка Из НоваяТаблица.Колонки Цикл
		МассивПолей.Добавить(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("	Т.%1 КАК %1", Колонка.Имя));
	КонецЦикла;
	
	ТекстПоляТаблицы = СтрСоединить(МассивПолей, "," + Символы.ПС);
	ТекстПоляИндексирования = ?(ПоляИндексирования = "", "", "ИНДЕКСИРОВАТЬ ПО " + ПоляИндексирования);
	
	ТекстЗапросаВТ = СтрЗаменить(ТекстЗапросаВТ, "&Поля", ТекстПоляТаблицы); // @Query-part-1
	ТекстЗапросаВТ = СтрЗаменить(ТекстЗапросаВТ, "ИмяПриемника", ИмяТаблицы);
	ТекстЗапросаВТ = ТекстЗапросаВТ + Символы.ПС + ТекстПоляИндексирования;
	
	Запрос.Текст = ТекстЗапросаУничтожитьВТ + ТекстЗапросаВТ;
	Запрос.УстановитьПараметр("Таблица", НоваяТаблица);
	
	Запрос.Выполнить();
	
КонецПроцедуры

Функция ИмяОбъектаИзПроцедурыОбработки(ИмяПроцедурыОбработки)
	
	ЧастиИмени = СтрРазделить(ИмяПроцедурыОбработки, ".");
	Если ЧастиИмени.Количество() = 2 Тогда
		ИмяОбъекта = "ОбщийМодуль." + ЧастиИмени[0];
	Иначе
		ЧастиИмени[0] = ЕдинственноеЧисло[ЧастиИмени[0]];
		ЧастиИмени.Удалить(ЧастиИмени.ВГраница());
		ИмяОбъекта = СтрСоединить(ЧастиИмени, ".");
	КонецЕсли;
	
	Возврат ИмяОбъекта;
	
КонецФункции

Процедура ВывестиСообщениеОбОшибках(БросатьИсключение = Истина)
	
	Если БросатьИсключение Тогда
		ИмяСобытия = НСтр("ru = 'Построение очереди обработчиков обновления'", ОбщегоНазначения.КодОсновногоЯзыка());
		СписокПроблемныхОбработчиков = "";
		Для Каждого Ошибка Из Ошибки Цикл
			Если НЕ ПустаяСтрока(Ошибка.Обработчик) Тогда
				ОбработчикиОшибки = СтрРазделить(Ошибка.Обработчик, Символы.ПС);
				Если ОбработчикиОшибки.Количество() = 1 Тогда
					ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(Ошибка.ОбъектМетаданных);
				КонецЕсли;
				ОбработчикиОшибки = СтрРазделить(Ошибка.Обработчик, Символы.ПС);
				Для Каждого Обработчик Из ОбработчикиОшибки Цикл
					Если СтрНайти(СписокПроблемныхОбработчиков, Обработчик) = 0 Тогда
						СписокПроблемныхОбработчиков = СписокПроблемныхОбработчиков + Обработчик + Символы.ПС;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
			ЗаписьЖурналаРегистрации(
				ИмяСобытия,
				УровеньЖурналаРегистрации.Ошибка,
				ОбъектМетаданных,
				Ошибка.Обработчик,
				Ошибка.Сообщение);
		КонецЦикла;
		ТекстИсключения = НСтр("ru = 'При построении очереди отложенных обработчиков обнаружены ошибки.
			|Необходимо их исправить с помощью встроенной обработки ""Описание обработчиков обновления"".
			|Для этого требуется запустить конфигурацию с параметром запуска ""%1"".
			|Ошибки перечислены в журнале регистрации.
			|
			|Список проблемных обработчиков обновления:'");
		ТекстИсключения = СтрЗаменить(ТекстИсключения, "%1", "ОтключитьЛогикуНачалаРаботыСистемы");
		ВызватьИсключение ТекстИсключения + Символы.ПС + СписокПроблемныхОбработчиков;
	Иначе
		Для Каждого Ошибка Из Ошибки Цикл
			ОбщегоНазначения.СообщитьПользователю(Ошибка.Сообщение);
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ЕстьЦиклВыполненияОбработчиков

// Проверяет наличие зацикленности выполнения по данным приоритетов для всех обработчиков.
//
// Возвращаемое значение:
//   Булево - Истина если есть зацикленность выполнения
//
Функция ЕстьЦиклВыполненияОбработчиков(ПроверяемыйОбработчик = Неопределено, Знач ПриоритетыОбработчика = Неопределено, СообщатьОбОшибках = Ложь)

	Если ПриоритетыВыполнения.Количество() = 0 Тогда
		Возврат Ложь;
	КонецЕсли;
	
	СписокРебер = ПриоритетыВыполнения.Выгрузить(, "Ссылка, Обработчик2, Порядок");
	Если ПриоритетыОбработчика <> Неопределено Тогда
		ОбратныйПорядок = ОбратныйПорядок();
		Для Каждого НовыйПриоритет Из ПриоритетыОбработчика Цикл
			
			Отбор = Новый Структура("Ссылка,Обработчик2");
			ЗаполнитьЗначенияСвойств(Отбор, НовыйПриоритет);
			НайденныеРебра = СписокРебер.НайтиСтроки(Отбор);
			Если НайденныеРебра.Количество() = 0 Тогда
				НовоеРебро = СписокРебер.Добавить();
				ЗаполнитьЗначенияСвойств(НовоеРебро, НовыйПриоритет);
			Иначе
				ЗаполнитьЗначенияСвойств(НайденныеРебра[0], НовыйПриоритет);
				Отбор.Ссылка = НовыйПриоритет.Обработчик2;
				Отбор.Обработчик2 = НовыйПриоритет.Ссылка;
				НайденныеРебра = СписокРебер.НайтиСтроки(Отбор);
				НайденныеРебра[0].Порядок = ОбратныйПорядок[НовыйПриоритет.Порядок];
			КонецЕсли;
			
		КонецЦикла;
	КонецЕсли;
	СписокРебер.Колонки.Ссылка.Имя = "Начало";
	СписокРебер.Колонки.Обработчик2.Имя = "Конец";

	ЛюбыеЗависимости = СписокРебер.НайтиСтроки(Новый Структура("Порядок", "Любой"));
	Для Каждого ЛюбаяЗависимость Из ЛюбыеЗависимости Цикл
		СписокРебер.Удалить(ЛюбаяЗависимость);
	КонецЦикла;
	
	ЗависимостиДо = СписокРебер.НайтиСтроки(Новый Структура("Порядок", "До"));
	Для Каждого ЗависимостьДо Из ЗависимостиДо Цикл
		Начало = ЗависимостьДо.Начало;
		ЗависимостьДо.Начало = ЗависимостьДо.Конец;
		ЗависимостьДо.Конец = Начало;
	КонецЦикла;
	
	СписокРебер.Колонки.Удалить("Порядок");
	ОптимизироватьСписокРебер(СписокРебер);
	СписокВершин = СписокВершин(СписокРебер);
	СписокСмежности = СписокСмежности(СписокРебер, СписокВершин);
	ИндексПроверяемогоОбработчика = Неопределено;
	
	Если ПроверяемыйОбработчик <> Неопределено Тогда
		Отбор = Новый Структура("Значение", ПроверяемыйОбработчик);
		НайденныеСтроки = СписокВершин.НайтиСтроки(Отбор);
		Если НайденныеСтроки.Количество() = 0 Тогда
			Возврат Ложь;
		КонецЕсли;
		СтрокаПроверяемогоОбработчика = НайденныеСтроки[0];
		ИндексПроверяемогоОбработчика = СписокВершин.Индекс(СтрокаПроверяемогоОбработчика);
	КонецЕсли;
	
	ЦиклыГрафа = НайтиЦиклыГрафа(СписокВершин, СписокСмежности, ИндексПроверяемогоОбработчика);
	ЕстьЦикл = ЦиклыГрафа.Количество() > 0;
	
	Если ЕстьЦикл Тогда
		
		Для Каждого ЦиклГрафа Из ЦиклыГрафа Цикл
			
			ПолныйПуть = Новый Массив;
			Для Каждого Ссылка Из ЦиклГрафа Цикл
				Описание = ОбработчикиОбновления.Найти(Ссылка, "Ссылка");
				ПолныйПуть.Добавить(Описание.Процедура);
			КонецЦикла;
			ТекстПути = СтрСоединить(ПолныйПуть, Символы.ПС);
			
			ТекстСообщения = НСтр("ru = 'Обнаружен цикл порядка выполнения:'") + Символы.ПС + "%Путь%";
			ТекстСообщения = СтрЗаменить(ТекстСообщения, "%Путь%", ТекстПути);
			
			ДобавитьОшибку(ТекстПути, ТекстСообщения);
			Если СообщатьОбОшибках Тогда
				ОбщегоНазначения.СообщитьПользователю(ТекстСообщения);
			КонецЕсли;
			
		КонецЦикла;
	КонецЕсли;
	
	Возврат ЕстьЦикл;
	
КонецФункции

#Область ПоискЦиклов

Процедура ДобавитьЦиклВРезультатПоиска(Параметры)
	
	НачалоЦикла = Параметры.НачалоЦикла;
	Вершина = Параметры.КонецЦикла;
	Путь = Параметры.Путь;
	
	СтруктураЦикла = Новый Массив;
	СтруктураЦикла.Добавить(НачалоЦикла);
	
	Пока Вершина <> НачалоЦикла Цикл
		СтруктураЦикла.Добавить(Вершина);
		Вершина = Путь[Вершина];
	КонецЦикла;
	
	СтруктураЦикла.Добавить(НачалоЦикла);
	ПеревернутьМассив(СтруктураЦикла);
	Параметры.Циклы.Добавить(СтруктураЦикла);
	
КонецПроцедуры

Процедура ЗаполнитьВершиныЗначениями(МассивВершин, СписокВершин)
	
	Для ИндексВершины = 0 По МассивВершин.ВГраница() Цикл
		МассивВершин[ИндексВершины] = СписокВершин[МассивВершин[ИндексВершины]].Значение;
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаполнитьЦиклыЗначениями(Параметры)
	
	СписокВершин = Параметры.СписокВершин;
	
	Для Каждого СтруктураЦикла Из Параметры.Циклы Цикл
		ЗаполнитьВершиныЗначениями(СтруктураЦикла, СписокВершин);
	КонецЦикла;
	
КонецПроцедуры

Процедура ОптимизироватьСписокРебер(СписокРебер)
	
	СписокРебер.Свернуть("Начало, Конец");
	СписокРебер.Индексы.Добавить("Начало");
	
КонецПроцедуры

Процедура ПеревернутьМассив(Массив)
	
	ИндексНачала = 0;
	ИндексКонца = Массив.ВГраница();
	
	Пока ИндексНачала < ИндексКонца Цикл
		Значение = Массив[ИндексНачала];
		Массив[ИндексНачала] = Массив[ИндексКонца];
		Массив[ИндексКонца] = Значение;
		ИндексНачала = ИндексНачала + 1;
		ИндексКонца = ИндексКонца - 1;
	КонецЦикла;
	
КонецПроцедуры

Процедура ПоискВГлубинуГрафа(ВершинаВыхода, Параметры)
	
	СостоянияВершин = Параметры.СостоянияВершин;
	СостоянияВершин[ВершинаВыхода] = 1;
	ВершиныВхода = Параметры.СписокСмежности[ВершинаВыхода];
	
	Если ВершиныВхода <> Неопределено Тогда
		Для ИндексВершиныВхода = 0 По ВершиныВхода.Количество() - 1 Цикл
			ВершинаВхода = ВершиныВхода[ИндексВершиныВхода];
			СостояниеВершиныВхода = СостоянияВершин[ВершинаВхода];
			
			Если СостояниеВершиныВхода = Неопределено Тогда
				Параметры.Путь[ВершинаВхода] = ВершинаВыхода;
				ПоискВГлубинуГрафа(ВершинаВхода, Параметры);
			ИначеЕсли СостояниеВершиныВхода = 1 Тогда
				Параметры.НачалоЦикла = ВершинаВхода;
				Параметры.КонецЦикла = ВершинаВыхода;
				ДобавитьЦиклВРезультатПоиска(Параметры);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	СостоянияВершин[ВершинаВыхода] = 2;
	
КонецПроцедуры

Процедура УдалитьЛишниеЦиклы(Циклы)
	
	ИсходныеЦиклы = СоответствиеПредставленийИЗначенийЦиклов(Циклы);
	НормализованныеЦиклы = Новый Массив;
	
	Для Каждого ИсходныйЦикл Из ИсходныеЦиклы Цикл
		НормализованныйЦикл = НормализоватьЦикл(ИсходныйЦикл.Значение);
		НормализованныеЦиклы.Добавить(НормализованныйЦикл);
	КонецЦикла;
	
	УникальныеЦиклы = СоответствиеПредставленийИЗначенийЦиклов(НормализованныеЦиклы);
	Циклы.Очистить();
	
	Для Каждого УникальныйЦикл Из УникальныеЦиклы Цикл
		Циклы.Добавить(УникальныйЦикл.Значение);
	КонецЦикла;
	
КонецПроцедуры

Функция ИндексМинимальногоЗначенияВМассиве(Массив)
	
	Если Массив.Количество() = 0 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Минимум = Массив[0];
	ИндексМинимума = 0;
	
	Для Индекс = 1 По Массив.ВГраница() Цикл
		Значение = Массив[Индекс];
		
		Если Значение < Минимум Тогда
			Минимум = Значение;
			ИндексМинимума = Индекс;
		КонецЕсли;
	КонецЦикла;
	
	Возврат ИндексМинимума;
	
КонецФункции

Функция НайтиЦиклыГрафа(СписокВершин, СписокСмежности, НачальнаяВершина = Неопределено)
	
	ПараметрыПоиска = НовыеПараметрыПоискаВГлубинуГрафа(СписокВершин, СписокСмежности);
	КоличествоВершин = СписокВершин.Количество();
	
	Если НачальнаяВершина = Неопределено Тогда
		Для ИндексВершиныВыхода = 0 По КоличествоВершин - 1 Цикл
			ПараметрыПоиска.СостоянияВершин = Новый Массив(КоличествоВершин);
			ПоискВГлубинуГрафа(ИндексВершиныВыхода, ПараметрыПоиска);
		КонецЦикла;
	Иначе
		ПоискВГлубинуГрафа(НачальнаяВершина, ПараметрыПоиска);
	КонецЕсли;
	
	УдалитьЛишниеЦиклы(ПараметрыПоиска.Циклы);
	ЗаполнитьЦиклыЗначениями(ПараметрыПоиска);
	
	Возврат ПараметрыПоиска.Циклы;
	
КонецФункции

Функция НовыеПараметрыПоискаВГлубинуГрафа(СписокВершин, СписокСмежности)
	
	КоличествоВершин = СписокВершин.Количество();
	
	ПараметрыПоиска = Новый Структура;
	ПараметрыПоиска.Вставить("СписокВершин", СписокВершин);
	ПараметрыПоиска.Вставить("СписокСмежности", СписокСмежности);
	ПараметрыПоиска.Вставить("СостоянияВершин", Новый Массив(КоличествоВершин));
	ПараметрыПоиска.Вставить("Путь", Новый Массив(КоличествоВершин));
	ПараметрыПоиска.Вставить("Циклы", Новый Массив);
	ПараметрыПоиска.Вставить("НачалоЦикла");
	ПараметрыПоиска.Вставить("КонецЦикла");
	
	Возврат ПараметрыПоиска;
	
КонецФункции

Функция НормализоватьЦикл(СтруктураЦикла)
	
	СтруктураЦикла.Удалить(СтруктураЦикла.ВГраница());
	ИндексМинимума = ИндексМинимальногоЗначенияВМассиве(СтруктураЦикла);
	НормализованныйЦикл = ЦиклическиСдвинутыйМассив(СтруктураЦикла, -ИндексМинимума);
	НормализованныйЦикл.Добавить(НормализованныйЦикл[0]);
	
	Возврат НормализованныйЦикл;
	
КонецФункции

Функция СоответствиеПредставленийИЗначенийЦиклов(Циклы)
	
	Соответствие = Новый Соответствие;
	
	Для Каждого СтруктураЦикла Из Циклы Цикл
		ПредставлениеЦикла = СтрСоединить(СтруктураЦикла, " → ");
		Значение = Соответствие[ПредставлениеЦикла];
		
		Если Значение = Неопределено Тогда
			Соответствие[ПредставлениеЦикла] = СтруктураЦикла;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Соответствие;
	
КонецФункции

Функция СписокВершин(СписокРебер)
	
	ВершиныВыхода = СписокРебер.Скопировать(, "Начало");
	ВершиныВхода = СписокРебер.Скопировать(, "Конец");
	ВершиныВхода.Свернуть("Конец");
	
	Для Каждого ВершинаВхода Из ВершиныВхода Цикл
		ВершинаВыхода = ВершиныВыхода.Добавить();
		ВершинаВыхода.Начало = ВершинаВхода.Конец;
	КонецЦикла;
	
	ВершиныВыхода.Свернуть("Начало");
	ВершиныВыхода.Колонки.Начало.Имя = "Значение";
	ВершиныВыхода.Индексы.Добавить("Значение");
	
	Возврат ВершиныВыхода;
	
КонецФункции

Функция СписокСмежности(СписокРебер, СписокВершин)
	
	КоличествоВершин = СписокВершин.Количество();
	СписокСмежности = Новый Массив(КоличествоВершин);
	ОтборВСпискеРебер = Новый Структура("Начало");
	ОтборВСпискеВершин = Новый Структура("Значение");
	
	Для ИндексВершины = 0 По КоличествоВершин - 1 Цикл
		ВершинаВыхода = СписокВершин[ИндексВершины].Значение;
		ОтборВСпискеРебер.Начало = ВершинаВыхода;
		ВершиныВхода = СписокРебер.НайтиСтроки(ОтборВСпискеРебер);
		КоличествоВершинВхода = ВершиныВхода.Количество();
		
		Если КоличествоВершинВхода > 0 Тогда
			СписокВершинВхода = Новый Массив(КоличествоВершинВхода);
			СписокСмежности[ИндексВершины] = СписокВершинВхода;
			
			Для ИндексВершиныВхода = 0 По КоличествоВершинВхода - 1 Цикл
				ВершинаВхода = ВершиныВхода[ИндексВершиныВхода].Конец;
				ОтборВСпискеВершин.Значение = ВершинаВхода;
				СписокВершинВхода[ИндексВершиныВхода] = СписокВершин.Индекс(СписокВершин.НайтиСтроки(ОтборВСпискеВершин)[0]);
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	
	Возврат СписокСмежности;
	
КонецФункции

Функция ЦиклическиСдвинутыйМассив(Массив, Смещение)
	
	Количество = Массив.Количество();
	СдвинутыйМассив = Новый Массив(Количество);
	
	Для Индекс = 0 По Массив.ВГраница() Цикл
		СмещениеИсточника = Индекс - Смещение + ?(Смещение < 0, 0, Количество);
		ИндексИсточника = СмещениеИсточника % Количество;
		СдвинутыйМассив[Индекс] = Массив[ИндексИсточника];
	КонецЦикла;
	
	Возврат СдвинутыйМассив;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#Область Прочее

Процедура УстановитьНомерОчереди(ИтерацииОбновления)
	
	ИменаКолонок = "Подсистема,ИмяОсновногоСерверногоМодуля";
	Подсистемы = ОбработчикиОбновления.Выгрузить(,ИменаКолонок);
	Подсистемы.Свернуть(ИменаКолонок);
	
	Для Каждого Библиотека Из ИтерацииОбновления Цикл
		
		Отбор = Новый Структура("РежимВыполнения", "Отложенно");
		Отбор.Вставить("ОчередьОтложеннойОбработки", 0);
		ОтложенныеОбработчики = Библиотека.Обработчики.НайтиСтроки(Отбор); // см. ОбновлениеИнформационнойБазы.НоваяТаблицаОбработчиковОбновления()
		Для Каждого Обработчик Из ОтложенныеОбработчики Цикл
			Отбор = Новый Структура;
			Отбор.Вставить("Версия", Обработчик.Версия);
			Отбор.Вставить("Процедура", Обработчик.Процедура);
			Отбор.Вставить("Идентификатор", Строка(Обработчик.Идентификатор));
			НайденныеОписания = ОбработчикиОбновления.НайтиСтроки(Отбор);
			Для Каждого Описание Из НайденныеОписания Цикл
				Обработчик.ОчередьОтложеннойОбработки = Описание.НоваяОчередь;
			КонецЦикла;
		КонецЦикла;// по отложенным обработчикам
		
	КонецЦикла;// по библиотекам
	
КонецПроцедуры

// Возвращает время прошедшее между указанными датами в формате "00:00:00".
// Если задан параметр СтруктураВремени, то в нем возвращаются отдельные значения Часы, Минуты, Секунды.
// если ВремяНачала = 0 преобразовывает дату в формат времени возвращает СтруктуруВремени если попросить.
//
// Параметры:
//   ВремяОкончания - Дата - время окончания.
//   ВремяНачала - Дата - время начала.
//   СтруктураВремени - Структура - составляющие части в отдельности:
//    * Часы - Число
//    * Минуты - Число
//    * Секунды - Число
//    * РазностьВремениСек - Число
//
// Возвращаемое значение:
//   Строка
//
Функция РазностьВремени(ВремяОкончания, ВремяНачала = 0, СтруктураВремени = Неопределено)
	Разность = ВремяОкончания - ВремяНачала;
	РазностьВремениСек = Макс(-Разность,Разность);
	Часы = Цел(РазностьВремениСек/3600);
	Минуты = Цел(РазностьВремениСек/60) - 60*Часы;
	Секунды = РазностьВремениСек - 60*Минуты - 60*60*Часы;
	СтруктураВремени = Новый Структура;
	СтруктураВремени.Вставить("Часы",Часы);
	СтруктураВремени.Вставить("Минуты",Минуты);
	СтруктураВремени.Вставить("Секунды",Секунды);
	СтруктураВремени.Вставить("РазностьВремениСек",РазностьВремениСек);
	Возврат  ?(СтрДлина(Строка(Часы))    = 1,"0" + Строка(Часы),    Строка(Часы))  +":"
			+?(СтрДлина(Строка(Минуты))  = 1,"0" + Строка(Минуты),  Строка(Минуты))+":"
			+?(СтрДлина(Строка(Окр(Секунды))) = 1,"0" + Строка(Секунды), Строка(Секунды));
КонецФункции

// Возвращает числовое представление номера версии.
//
// Параметры:
//   Версия - Строка - номер версии в формате Х.Х.ХХ.ХХХ 
//
// Возвращаемое значение:
//   Число - номер версии преобразованный в целое число
//
Функция ВерсияЧислом(Версия) Экспорт
	
	Результат = 0;
	
	МассивВерсий = Версия;
	Если ТипЗнч(Версия) = Тип("Строка") Тогда
		МассивВерсий = СтрРазделить(Версия, ".");
	КонецЕсли;
	Если МассивВерсий.Количество() = 4 Тогда
		Результат = Число(МассивВерсий[0]) * 10000000 + Число(МассивВерсий[1]) * 1000000 
				  + Число(МассивВерсий[2]) * 10000 + Число(МассивВерсий[3]);
					
	ИначеЕсли МассивВерсий.Количество() = 3 Тогда
		Результат = Число(МассивВерсий[0]) * 1000000 + Число(МассивВерсий[1]) * 10000
				  + Число(МассивВерсий[2]);
					
	ИначеЕсли МассивВерсий.Количество() = 2 Тогда
		Результат = Число(МассивВерсий[0]) * 10000 + Число(МассивВерсий[1]);
		
	КонецЕсли;
		
	Возврат Результат;
	
КонецФункции

// Возвращает список разрабатываемых подсистем в конфигурации 
//
// Возвращаемое значение:
//   Массив из Строка - имена подсистем в том виде, в котором они заданы в общих модулях ОбновлениеИнформационнойБазыХХХ
//
Функция РазрабатываемыеПодсистемы() Экспорт
	
	Результат = Новый Массив;
	ОбновлениеИнформационнойБазыПереопределяемый.ПриФормированииСпискаРазрабатываемыхПодсистем(Результат);
	ОбновлениеИнформационнойБазыПереопределяемый.ПриФормированиеСпискаРазрабатываемыхПодсистем(Результат); // АПК:222 Для обратной совместимости.
	Возврат Результат;
	
КонецФункции

Функция ЕщеСведения()
	Результат = Новый Структура("РежимВыполненияОтложенныхОбработчиков,ПорядокБиблиотеки,Порядок");
	Результат.Порядок = Перечисления.ПорядокОбработчиковОбновления.Обычный;
	Возврат Результат;
КонецФункции

Функция ЗаполнитьПриоритетыТиповМетаданных()
	
	ПриоритетыТиповМетаданных = Новый Соответствие;
	ПриоритетыТиповМетаданных.Вставить("Константа", 10);
	ПриоритетыТиповМетаданных.Вставить("Справочник", 20);
	ПриоритетыТиповМетаданных.Вставить("ПланСчетов", 30);
	ПриоритетыТиповМетаданных.Вставить("ПланВидовХарактеристик", 40);
	ПриоритетыТиповМетаданных.Вставить("ПланОбмена", 50);
	ПриоритетыТиповМетаданных.Вставить("ПланВидовРасчета", 60);
	ПриоритетыТиповМетаданных.Вставить("Задача", 70);
	ПриоритетыТиповМетаданных.Вставить("БизнесПроцесс", 80);
	ПриоритетыТиповМетаданных.Вставить("РегистрСведенийНезависимый", 90);
	ПриоритетыТиповМетаданных.Вставить("Документ", 100);
	ПриоритетыТиповМетаданных.Вставить("ЖурналДокументов", 110);
	ПриоритетыТиповМетаданных.Вставить("РегистрСведений", 120);
	ПриоритетыТиповМетаданных.Вставить("РегистрНакопления", 130);
	ПриоритетыТиповМетаданных.Вставить("РегистрРасчета", 140);
	ПриоритетыТиповМетаданных.Вставить("РегистрБухгалтерии", 150);

	ОбновлениеИнформационнойБазыПереопределяемый.ПриЗаполненииПриоритетовТиповМетаданных(ПриоритетыТиповМетаданных);
	
	Возврат ПриоритетыТиповМетаданных;

КонецФункции

Функция ПорядокТипаОбъекта(ПолноеИмя)
	
	Если СтрЧислоВхождений(ПолноеИмя, ".") = 0 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Имена = СтрРазделить(ПолноеИмя,".");
	ТипОбъекта = Имена[0];
	Если ТипОбъекта = "РегистрСведений" Тогда
		МетаданныеОбъекта = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмя);
		Если МетаданныеОбъекта.РежимЗаписи =  Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый Тогда
			ТипОбъекта = ТипОбъекта + "Независимый";
		КонецЕсли;
	КонецЕсли;
	
	Результат = ПриоритетыТиповМетаданных[ПолноеИмя];
	Если Результат = Неопределено Тогда
		Результат = ПриоритетыТиповМетаданных[ТипОбъекта];
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Возвращает соответствие прямого порядка обратному.
// Для прямого порядка "До" обратный порядок "После". 
// Для прямого порядка "После" обратный порядок "До". 
// Для прямого порядка "Любой" обратный порядок "Любой".
//
// Возвращаемое значение:
//   Соответствие
//
Функция ОбратныйПорядок() Экспорт
	
	ИнверсныйПорядок = Новый Соответствие;
	ИнверсныйПорядок.Вставить("До","После");
	ИнверсныйПорядок.Вставить("После","До");
	ИнверсныйПорядок.Вставить("Любой","Любой");
	Возврат ИнверсныйПорядок;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#Область Инициализация

ИнициализацияКонстант();
ЗаполнитьПриоритетыТиповМетаданных();

#КонецОбласти

#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли
